Упражнение 39 (подсказки и решения)

Рассмотрим решение, которое учитывает даты сражений, но все же является не вполне верным:

SELECT t.name
FROM (SELECT o.ship AS name, battle
      FROM Outcomes o
      ) t, Battles b
WHERE t.battle = b.name
GROUP BY t.name
HAVING (SELECT result
        FROM Outcomes, Battles
        WHERE ship = t.name AND
              battle = name AND
              date = MIN(b.date)
        ) = 'damaged' AND
       (SELECT result
        FROM Outcomes, Battles
        WHERE ship = t.name AND
              battle = name AND
              date = MAX(b.date)
        ) IN ('damaged', 'ok', 'sunk') AND
        COUNT(t.name) > 1;
mssql
🚫
[[ error ]]
[[ column ]]
[[ value ]]

В этом решении участвовавшие в сражениях корабли группируются по именам, после чего остаются только те которые отвечают следующим условиям:

  • в сражении с минимальной датой корабль должен быть поврежден;
  • в сражении с максимальной датой результат сражения может быть любым;
  • число сражений должно быть больше одного.

Логическая ошибка, допущенная в этом запросе, заключается в том, что если корабль участвовал более чем в двух сражениях, то в первом своем сражении (сражении с минимальной датой) корабль может и не быть поврежден. Более точно, результат его сражения должен быть ok, чтобы представленное выше решение перестало давать правильный результат. Действительно, потоплен корабль быть не может, иначе бы он не участвовал в более поздних сражениях. Если бы он был поврежден, то запрос его бы справедливо учитывал. А вот если последовательность результатов будет следующей: ok, damaged и любой из трех возможных, то представленное решение его бы не выводило, хотя такой корабль и отвечает условиям задачи.

Вернуться к обсуждению упражнения 39

Решить задачу на SQL-EX.RU