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

Упражнение 70 стр. 4

Решение 3.7.4

Консоль
Выполнить
  1. SELECT DISTINCT battle
  2. FROM (SELECT battle, country
  3. FROM (SELECT battle, country
  4. FROM Outcomes INNER JOIN
  5. Classes ON ship = class
  6. UNION
  7. SELECT battle, country
  8. FROM Outcomes o INNER JOIN
  9. Ships s ON o.ship = s.name INNER JOIN
  10. Classes c ON s.class = c.class
  11. ) x
  12. GROUP BY battle, country
  13. HAVING COUNT(*) > 2
  14. ) y;

Во внутреннем подзапросе объединяются два запроса. В первом из них

Консоль
Выполнить
  1. SELECT battle, country
  2. FROM Outcomes INNER JOIN
  3. Classes ON ship = class;
определяется страна и сражения, в которых принимали участие головные корабли из этой страны. Во втором запросе

Консоль
Выполнить
  1. SELECT battle, country
  2. FROM Outcomes o INNER JOIN
  3. Ships s ON o.ship = s.name INNER JOIN
  4. Classes c ON s.class = c.class;
определяется страна и сражения для тех кораблей, которые имеются в таблице Ships. Соединение с таблицей Classes необходимо, чтобы узнать страну, владеющую кораблем.

Использование для объединения предложения UNION устраняет дубликаты. С одной стороны, это кажется правильным, так как головной корабль может находиться как в таблице Outcomes, так и в таблице Ships. С другой стороны, после удаления дубликатов в результирующем наборе останется только одна уникальная пара {сражение, страна}, а это означает, что для любого числа кораблей из одной страны, останется лишь одна строка для каждого из сражений. В результате последующая группировка попросту излишней, как предложение HAVING.

Первое, что приходит в голову, — написать UNION ALL вместо UNION, то есть учесть все дубликаты. Но, как уже понятно из предыдущего обсуждения, тогда для одного головного корабля, участвующего в некотором сражении, мы получим две строки, если этот корабль присутствует еще и в таблице Ships.

Как поступить? Автор предлагает два подхода. При первом подходе мы оставляем UNION, но подсчитываем не страны, а корабли. Тогда устранение дубликатов будет правильным. При втором подходе автор предполагает использование UNION ALL, но тогда нужно в одном из объединяемых запросов проверять, чтобы учитываемый корабль не присутствовал в другой таблице, тем самым, подсчитывая его один раз.

Какой из способов предпочесть, зависит не только от наших предпочтений, но и от стоимости плана выполнения запроса. Предлагаем самостоятельно оценить планы, предварительно решив задачу двумя описанными способами.

ПиР

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

Страницы: 1 2 3 4
Тэги:
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