Довідка - по - sql (dml) як об'єднати дані з двох стовпців в один без використання union і join

Такі питання із завидною регулярністю з'являються на сторінках різних форумів. До слова сказати, для мене досі залишається загадкою, чому при цьому ставиться додаткову умову не використовувати UNION і / або JOIN. Можу лише припустити, що це питання, які задають на співбесіді при прийомі на роботу.

Ліричний відступ. Здогадуюся, як відповів би на це питання Джо Селко: в наявності помилка проектування, яка полягає в тому, що один атрибут розщеплений на два. Однак залишимо осторонь питання проектування і перейдемо до вирішення цього завдання.

Створимо тестову таблицю і додамо в неї трохи даних:

Отже, є таблиця T, яка містить два стовпці з даними одного типу:

Потрібно забрати наступний результат:

Мені відомі три способи, які реалізуються стандартними засобами інтерактивного мови SQL.

1. UNION ALL

2. FULL JOIN

Щоб не втратити дублікати, що знаходяться в різних стовпчиках, виконаємо повне з'єднання (FULL JOIN) за свідомо помилковому предикату, скажімо, 1 = 2:

Далі використовуємо функцію COALESCE. яка дасть нам все, що потрібно:

3. UNPIVOT

Значення з стовпців col1 і col2 збираються в одному стовпці col допоміжної таблиці unpvt. Однак є одна особливість у використанні операторів PIVOT і UNPIVOT - вони не враховують NULL-значення. Результат останнього запиту буде таким:

Це перешкода на шляху до вирішення нашої задачі можна подолати, якщо замінити NULL-значення на вході оператора UNPIVOT псевдозначеніем, тобто значенням, якого свідомо не може бути у вихідних даних, а потім виконати зворотне перетворення:

Тут COALESCE (colx, 777) замінює NULL-значення в стовпці colx на 777, а функція NULLIF (col, 777) виконує зворотне перетворення.

Останнє рішення дає нам необхідний результат, проте містить одну ваду - значення 777 може рано чи пізно з'явитися в даних, що буде призводити до невірних результатів. Щоб усунути цей огріх, можна використовувати значення іншого типу, якого свідомо не може бути присутнім в целочисленном стовпці, наприклад, символ 'x'. Природно, щоб застосувати цей підхід, для сумісності типів цілочисельний тип стовпців слід конвертувати до символьного типу, виконавши при необхідності зворотне перетворення кінцевого результату:

Кілька слів про ефективність представлених рішень. Згідно з планом виконання запиту, основні витрати обумовлені читанням даних (операція сканування таблиці - Table scan). Для двох перших рішень сканування виконується двічі, в той час як для останнього (UNPIVOT) - один раз, що навіть зумовлено його подвійну перевагу в продуктивності.

Є ще один варіант, який я використовую:

Декартово твір таблиці T з вибіркою з 2-х рядків дає "подвоєння" (кожна рядок таблиці повторюється 2 рази - для а = 1 і а = 2). Для першого випадку беремо значення з col1, а для другого - з col2.

Тут, звичайно, є і union, і join, але, по-моєму, в даному питанні цікавить саме єдине сканування таблиці.


Створення сайтів в Тюмені
Створюємо якісні та недорогі сайти, сайт візитка, корпоративний
professor-labs.ru
розрахунок кухні
Кухні, передпокої, меблеві фасади. Салони італійських кухонь
hanak.ru
Fantasy
filme-online-anschauen.com

Вправи SELECT (рейтингові етапи)