loading..
Русский    English
13:50
листать

Упражнение 56 стр. 5

Решение 3.12.5
Консоль
Выполнить
  1. SELECT t1.class, COUNT(*) AS cnt
  2. FROM (SELECT a.class, b.name
  3.       FROM Classes a LEFT JOIN
  4. -- соединение с Ships без головных кораблей:
  5.            Ships b ON a.class = b.class AND
  6.                       a.class <> b.name
  7.       ) AS t1 JOIN
  8. -- соединение либо по классу для головных кораблей, либо по имени
  9.       Outcomes t2 ON t1.class = t2.ship OR
  10.                      t1.name = t2.ship
  11. WHERE result = 'sunk'
  12. GROUP BY t1.class
  13. -- Выбираются классы кораблей, которые не попали в первый запрос.
  14. -- Это классы, не имеющие потопленных кораблей.
  15. UNION
  16. SELECT class, '0'
  17. FROM Classes
  18. WHERE class NOT IN (SELECT DISTINCT t1.class
  19.                     FROM (SELECT a.class, b.name
  20.                           FROM Classes a LEFT JOIN
  21.                                Ships b ON a.class = b.class AND
  22.                                           a.class <> b.name
  23.                           ) AS t1 JOIN
  24.                           Outcomes t2 ON t1.class = t2.ship OR
  25.                                          t1.name = t2.ship
  26.                     WHERE result = 'sunk'
  27.                     );


Решение 3.12.6
Консоль
Выполнить
  1. SELECT d.class class, (SELECT COUNT(f.result)
  2.                        FROM (SELECT c.result
  3.                              FROM Ships b LEFT OUTER JOIN
  4.                                   Outcomes c ON (b.name = c.ship)
  5.                              WHERE c.result = 'sunk' AND
  6.                                    d.class = b.class
  7.                              UNION ALL
  8.                              SELECT c.result
  9.                              FROM Outcomes c
  10.                              WHERE c.result = 'sunk' AND
  11.                                    d.class = c.ship
  12.                              ) f
  13.                        ) Sunks
  14. FROM Classes d;


Для анализа двух последних решений — 3.12.5 и 3.12.6 — рассмотрим следующие варианты данных. В таблице Ships (показаны только принципиальные для анализа столбцы):

name class
ship1_class_1 class_1
ship2_class_1 class_1

В таблице Outcomes:

ship result
ship1_class_1 sunk
class_1 sunk

Тогда согласно предикату соединения в решении 3.12.5

  1.      ON t1.class = t2.ship OR
  2.         t1.name = t2.ship
в результирующий набор дважды попадет корабль ship1_class_1 из таблицы Ships, так как для первой строки в таблице Outcomes у него совпадает имя корабля, а для второй — название класса. В результате получим 3 потопленных корабля, хотя на самом деле их только 2.

Решение задачи 3.12.6 даст нам здесь правильный результат, поскольку первый запрос в объединении (соединение по имени корабля) даст только ship1_class_1, а второй — только class_1. Однако это решение тоже не верно, что будет продемонстрировано на другом варианте данных.

В таблице Ships

name                class
ship1_class_2    class_2
class_2    class_2

В таблице Outcomes:

ship                  result
ship1_class_2    sunk
class_2             sunk

Первый запрос в объединении даст нам оба потопленных корабля класса class_2, а второй — головной корабль этого класса. Поскольку при объединении используется UNION ALL, то головной корабль дважды будет учтен в результирующем наборе, в результате чего мы опять получаем 3 вместо 2. Косметическое исправление UNION ALL на UNION не делает решение верным, так как здесь возникает та же ошибка, что и в решении 3.12.4, когда для любого количества потопленных кораблей класса в результат попадает только 1.

Кстати, решение 3.12.5 на этих данных тоже дает значение 3, но по другой причине, описанной выше.

ПиР

Решить упражнение на SQL-EX.RU

Bookmark and Share
Страницы: 1 2 3 4 5
Тэги:
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 Больше тэгов
Учебник обновлялся
месяц назад
https://exchangesumo.com/obmen/QIWIRUB-WEXRUB/
©SQL-EX,2008 [Развитие] [Связь] [О проекте] [Ссылки] [Team]
Перепечатка материалов сайта возможна только с разрешения автора.