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

Явные операции соединения стр. 3

UNION JOIN

Этот тип соединения был введен в стандарте SQL-92, но в более поздних версиях стандарта отсутствует. В частности, его уже нет в стандарте SQL2003 (ANSI и ISO). Как и многие другие конструкции языка SQL, соединение UNION JOIN является избыточным, поскольку его можно выразить через разность полного и внутреннего соединений. Формально это можно записать следующим образом:

  1. A UNION JOIN B :=
  2. (A FULL JOIN B)
  3. EXCEPT
  4. (A INNER JOIN B)

Ну, а если полное соединение не поддерживается (MySQL), то его можно получить объединением левого и правого внешних соединений. Тогда наша формула примет вид

  1. A UNION JOIN B :=
  2. ((A LEFT JOIN B)
  3. UNION
  4. (A RIGHT JOIN B))
  5. EXCEPT
  6. (A INNER JOIN B)

Давайте в качестве примера, где мог бы пригодиться этот тип соединения, рассмотрим следующую задачу.

Найти производителей, которые выпускают принтеры, но не ПК, или выпускают ПК, но не принтеры.

Будь у нас возможность использовать UNION JOIN, мы бы решили задачу так:

  1. SELECT * FROM
  2. (SELECT DISTINCT maker FROM Product WHERE type='pc') m_pc
  3. UNION JOIN
  4. (SELECT DISTINCT maker FROM Product WHERE type='printer') m_printer
  5. ON m_pc.maker = m_printer.maker;  

Воспользуемся формулой. Полное соединение производителей ПК и производителей принтеров даст нам как тех, кто производит что-то одно, так и тех, кто производит и то, и другое.

Консоль
Выполнить
  1. SELECT * FROM
  2. (SELECT DISTINCT maker FROM Product WHERE type='pc') m_pc
  3. FULL JOIN
  4. (SELECT DISTINCT maker FROM Product WHERE type='printer') m_printer
  5. ON m_pc.maker = m_printer.maker;  

Теперь вычтем из результата тех, кто производит и то, и другое (внутренее соединение):

Консоль
Выполнить
  1. SELECT m_pc.maker m1, m_printer.maker m2  FROM
  2. (SELECT maker FROM Product WHERE type='pc') m_pc
  3. FULL JOIN
  4. (SELECT maker FROM Product WHERE type='printer') m_printer
  5. ON m_pc.maker = m_printer.maker
  6. EXCEPT
  7. SELECT * FROM
  8. (SELECT maker FROM Product WHERE type='pc') m_pc
  9. INNER JOIN
  10. (SELECT maker FROM Product WHERE type='printer') m_printer
  11. ON m_pc.maker = m_printer.maker;

Попутно я убрал из этого решения избыточные DISTINCT, поскольку EXCEPT выполнит исключение дубликатов. Это единственный полезный тут урок, т.к. операцию взятия разности (EXCEPT) можно заменить простым предикатом:

  1. WHERE m_pc.maker IS NULL OR m_printer.maker IS NULL
или даже так

  1. m_pc.maker + m_printer.maker IS NULL
ввиду того, что конкатенация с NULL-значением дает NULL.

Консоль
Выполнить
  1. SELECT * FROM
  2. (SELECT DISTINCT maker FROM Product WHERE type='pc') m_pc
  3. FULL JOIN
  4. (SELECT DISTINCT maker FROM Product WHERE type='printer') m_printer
  5. ON m_pc.maker = m_printer.maker   
  6. WHERE m_pc.maker IS NULL OR m_printer.maker IS NULL;

 Наконец, чтобы представить результат в один столбец, воспользуемся функцией COALESCE:

Консоль
Выполнить
  1. SELECT COALESCE(m_pc.maker, m_printer.maker) FROM
  2. (SELECT DISTINCT maker FROM Product WHERE type='pc') m_pc
  3. FULL JOIN
  4. (SELECT DISTINCT maker FROM Product WHERE type='printer') m_printer
  5. ON m_pc.maker = m_printer.maker   
  6. WHERE m_pc.maker IS NULL OR m_printer.maker IS NULL;

Разумеется, это не единственный способ решения данной задачи. Он лишь демонстрирует замену репрессированного типа соединений.

Мне неизвестны СУБД, в которых было бы реализовано соединение UNION JOIN.

Следующая страница

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/to/KSPBKZT/
©SQL-EX,2008 [Развитие] [Связь] [О проекте] [Ссылки] [Team]
Перепечатка материалов сайта возможна только с разрешения автора.
Rambler's Top100