loading..
Русский    English
18:43
листать

Упражнение 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
ship1_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

Страницы: 1 2 3 4 5
Тэги:
ALL AVG battles CASE CAST CHAR CHARINDEX classes COALESCE Convert COUNT CTE DATEDIFF DATEPART DATETIME DELETE DISTINCT EXCEPT EXISTS EXTRACT FROM FULL JOIN GROUP BY Guadalcanal HAVING IN INNER JOIN insert INTERSECT ISNULL laptop LEFT LEFT OUTER JOIN LEN maker MAX MIN MySQL NOT IN NULL ORDER BY Outcome outcomes OVER PARTITION BY pc PIVOT PostgreSQL printer product Больше тэгов
Учебник обновлялся
несколько дней назад
©SQL-EX,2008 [Развитие] [Связь] [О проекте] [Ссылки] [Team]
Перепечатка материалов сайта возможна только с разрешения автора.
Rambler's Top100