Упражнение 57 (подсказки и решения) |
||
Ниже представлено решение, в котором правильно определяется число потопленных кораблей (хотя, на наш взгляд, весьма громоздко), однако неправильно подсчитывается общее число кораблей в классе.
Подсчет общего числа кораблей в классе выполняется здесь в предложении HAVING основного запроса. В подзапросе этого предложения для каждого класса из основного запроса выполняется объединение числа кораблей из таблицы Ships с числом кораблей (головных) из таблицы Outcomes при условии, что такие корабли не были учтены ранее (их нет в таблице Ships). Видно, что поскольку объединяются одноатрибутные отношения посредством оператора UNION, то если у нас имеется по одному кораблю и в одном, и другом наборе, мы заведомо получаем неверный результат в результате устранения дубликатов. Однако здесь это как бы не должно являться ошибкой, так как мы отбираем классы, имеющие в сумме более двух кораблей. А других возможных вариантов быть не должно, поскольку головной корабль если и есть, то он только один (несмотря на излишнее использование COUNT во втором запросе). И все же ошибка кроется именно здесь. Дело в том, что если головной корабль принимал участие более чем в одном сражении, то мы его учитываем по числу сражений, разумеется, если его нет в таблице Ships. Исправить это решение несложно, предлагаем вам сделать это самостоятельно. Однако можно написать и более простой (а также более эффективный) запрос. Перейти к обсуждению задачи 57 |