Книги и статьи по SQL Rambler's Top100 Switch language to: English 30 ноября 2020 г. 23:07:26


www.sql-ex.ru
Skip Navigation Links  

 

Print  Версия для печати

На главную страницу

Характерные ошибки при решении упражнений. Задача 43

Моисеенко С.И.

Для каждой страны определить год, когда на воду было спущено максимальное количество ее кораблей. В случае, если окажется несколько таких лет, взять минимальный из них. Вывод: страна, количество кораблей, год.

Устав отвечать на вопросы относительно этой задачи, я решил объяснить допускаемую при ее решении одну и ту же ошибку. Однако чтобы не лишать вас удовольствия самостоятельно решить эту задачу, упрощу формулировку.
Итак,
Определить год, когда на воду было спущено максимальное количество кораблей. Вывод: количество кораблей, год.

Определить распределение количества кораблей по годам можно так

SELECT launched [year], COUNT(*) cnt FROM Ships GROUP BY launched

Теперь нам нужно оставить из всех строк, возвращаемых этим запросом, только те, у которых количество (cnt) максимально, т.е.

>= ALL(SELECT COUNT(*) cnt FROM Ships GROUP BY launched)

Окончательно получим

SELECT * FROM
(
SELECT launched [year], COUNT(*) cnt FROM Ships GROUP BY launched
) x
WHERE cnt >= ALL(SELECT COUNT(*) cnt FROM Ships GROUP BY launched)

Тем не менее, здесь кроется ошибка. Эта ошибка не связана с формальным построением решения. Оно не вызывает сомнения. Как это обычно происходит при решении задач на сайте, ошибка заключается в неточном учете особенностей модели предметной области, а именно, ее ограничений. В данном случае - это допустимость того, что в базе данных могут быть корабли с неизвестным годом спуска на воду. Хочу здесь отметить, что если в описании предметной области не оговорено противное, неключевые поля допускают NULL-значения. Собственно, по умолчанию это и имеется в виду, когда мы создаем таблицу с помощью оператора CREATE TABLE.

Строить корабли - это не кроликов разводить :-). Корабли строятся годами. Поэтому, если для ряда кораблей год спуска на воду неизвестен (NULL), то велика вероятность того, что число таких кораблей будет больше, чем количество кораблей, спущенных на воду в любом реальном году. Особенность группировки заключается в том (и это оговорено в Стандарте), что NULL-значения трактуются как РАВНЫЕ. Следовательно, все корабли с неизвестным годом спуска на воду, будут просуммированы с годом NULL. Я полагаю, что результат не должен включать такую строку по той причине, что неизвестный год - не значит один и тот же. С этим можно, конечно, поспорить. Однако все споры сведутся к допустимости использования специфического значения NULL в реляционной модели. Дискуссии по этому поводу ведутся со времен создания этой модели Коддом Е.Ф., которому и принадлежит идея NULL-значения. Однако, насколько мне известно, достойной альтернативы предложено не было.

Возвращаясь к нашей задаче, я, в знак безграничного уважения к Кодду, внесу в решение следующее изменение:

SELECT * FROM
(
SELECT launched [year], COUNT(*) cnt FROM Ships
WHERE launched IS NOT NULL
GROUP BY launched
) x
WHERE cnt >= ALL(SELECT COUNT(*) cnt FROM Ships
WHERE launched IS NOT NULL
GROUP BY launched)

Приведенные здесь примеры можно выполнить непосредственно на сайте, установив флажок "Без проверки" на странице с упражнениями на SELECT.

Перейти к решению задачи #43

На главную страницу

Print  Версия для печати


Использование любых материалов данного сайта возможно только
при условии обязательного размещения прямой ссылки на сайт
http://www.sqlbooks.ru
на каждой странице, где размещены используемые материалы.

 Начало   Статьи    Книги 
Рейтинг@Mail.ru Rambler's Top100 Alt Упражнения по SQL: обучение, тестирование, сертификация по языку SQL Copyright c 2002-2006. All rights reserved.