Упражнение 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;
[[ column ]] |
---|
[[ value ]] |
В этом решении участвовавшие в сражениях корабли группируются по именам, после чего остаются только те которые отвечают следующим условиям:
- в сражении с минимальной датой корабль должен быть поврежден;
- в сражении с максимальной датой результат сражения может быть любым;
- число сражений должно быть больше одного.
Логическая ошибка, допущенная в этом запросе, заключается в том, что если корабль участвовал более чем в двух сражениях, то в первом своем сражении (сражении с минимальной датой) корабль может и не быть поврежден. Более точно, результат его сражения должен быть ok, чтобы представленное выше решение перестало давать правильный результат. Действительно, потоплен корабль быть не может, иначе бы он не участвовал в более поздних сражениях. Если бы он был поврежден, то запрос его бы справедливо учитывал. А вот если последовательность результатов будет следующей: ok, damaged и любой из трех возможных, то представленное решение его бы не выводило, хотя такой корабль и отвечает условиям задачи.