loading..
Русский    English
02:55
листать

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

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

Консоль
Выполнить
  1. SELECT class
  2. FROM Classes
  3. WHERE EXISTS (SELECT 1
  4. FROM Ships
  5. WHERE launched < 1941 AND
  6. Ships.class = Classes.class
  7. );

То есть здесь класс отождествляется с наличием головного корабля в БД, а именно, разыскивается класс, который имеет в БД корабль, спущенный на воду ранее 1941 года. Однако из описания предметной области следует, что не всегда есть корабль, имя которого совпадает с именем класса. Поэтому искать неучтенные в Ships головные корабли следует исключительно в таблице Outcomes.

Наконец, о неучтенном варианте в решении 5.3.3. Итак, возможна следующая ситуация. Имеется головной корабль с неизвестным годом спуска на воду. Более того, он может участвовать только в сражениях после 1941 года. Пусть для всех других корабли того же класса год спуска на воду тоже неизвестен (это допускается схемой данных). Однако, если хотя бы один из этих кораблей участвовал в сражении до 1941 года, то нам следует такой корабль включить в результирующий набор вместе с головным, так как головной корабль (если он есть!) должен быть спущен на воду ранее любого другого корабля аналогичного класса.

Вот решение, которое, казалось бы, учитывает все оговоренные моменты:

Консоль
Выполнить
  1. -- Корабли, спущенные на воду до 1941 года
  2. SELECT name
  3. FROM Ships
  4. WHERE launched < 1941
  5.  
  6. UNION
  7. -- Корабли, принимавшие участие в сражениях до 1941 года
  8. SELECT ship
  9. FROM Outcomes JOIN
  10. Battles ON Battles.name = Outcomes.battle
  11. WHERE date < '19410101'
  12.  
  13. UNION
  14. -- Головные корабли из Outcomes, в классе которых есть другие корабли,
  15. -- спущенные на воду до 1941 года
  16. SELECT ship
  17. FROM Outcomes
  18. WHERE ship IN (SELECT class
  19. FROM Ships
  20. WHERE launched < 1941
  21. )
  22.  
  23. UNION
  24. -- Головные корабли из Outcomes при условии, что хотя бы один из кораблей
  25. -- того же класса, участвовал в сражении до 1941 года
  26. SELECT ship
  27. FROM Outcomes
  28. WHERE Ship IN (SELECT class
  29. FROM Ships JOIN
  30. Outcomes ON Ships.name = Outcomes.ship JOIN
  31. Battles ON Battles.name = Outcomes.battle
  32. WHERE date < '19410101'
  33. );

Однако система все равно сообщает об ошибке…

Как уже было отмечено в пункте 3.5, головные корабли с неизвестным годом спуска на воду могут находиться не только в таблице Outcomes, но и в таблице Ships. Более того, такие корабли не будут учтены рассматриваемым запросом, если их нет в таблице Outcomes, то есть они либо не участвовали в сражениях, либо информация об их участии неизвестна.

Так что здесь чистая логика, и никаких подвохов.

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

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


Bookmark and Share
Тэги:
ALL AND AUTO_INCREMENT AVG battles CASE CAST CHAR CHARINDEX CHECK classes COALESCE CONSTRAINT Convert COUNT CROSS APPLY CTE DATEADD DATEDIFF DATENAME DATEPART DATETIME DDL DEFAULT DELETE DISTINCT DML EXCEPT EXISTS EXTRACT FOREIGN KEY FROM FULL JOIN GROUP BY Guadalcanal HAVING IDENTITY IN INFORMATION_SCHEMA INNER JOIN insert INTERSECT IS NOT NULL IS NULL ISNULL laptop LEFT LEFT OUTER JOIN LEN maker Больше тэгов
Учебник обновлялся
месяц назад
©SQL-EX,2008 [Развитие] [Связь] [О проекте] [Ссылки] [Team]
Перепечатка материалов сайта возможна только с разрешения автора.