loading..
Русский    English
16:41
листать

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

Bookmark and Share
Страницы: 1 2 3 4
Тэги:
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-BTC/
©SQL-EX,2008 [Развитие] [Связь] [О проекте] [Ссылки] [Team]
Перепечатка материалов сайта возможна только с разрешения автора.
Rambler's Top100