Всегда ли можно избежать использования UNION в SQL? - PullRequest
0 голосов
/ 18 декабря 2018

Предположим, у меня есть супер-простая таблица (называемая useful_table) с одним столбцом, как показано ниже:

+----------+
| a_number |
+----------+
|     2    |
|     4    |
|     8    |
+----------+

И предположим, у меня есть запрос с UNION:

  SELECT
    a_number
  FROM
    useful_table
  WHERE
    a_number = 2
UNION
  SELECT
    a_number + 1
  FROM
    useful_table
  WHERE
    a_number = 2
;

Я ожидаю, что результат будет:

+----------+
| a_number |
+----------+
|     2    |
|     3    |
+----------+

Пример запроса выполняется в Oracle, но он должен быть применим к другим диалектам.

Код установки здесь:

create table useful_table(a_number NUMBER);
insert into useful_table values (2);
insert into useful_table values (4);
insert into useful_table values (8);

Возможно ли преобразовать этот запрос?

Всегда ли можно преобразовать UNION s в альтернативу?

Допущения:

  • Я использую подмножество (Oracle) SQL, что означает:
    • Я не могу использовать временные таблицы.
    • Я не могу использовать UNION или UNION ALL.
  • Обе стороны UNION имеют доступ к данным из одной и той же таблицы, но могут по-разному изменять необработанные данные.

Ответы [ 3 ]

0 голосов
/ 18 декабря 2018

Всегда можно переписать UNION как FULL OUTER JOIN.

Так что

  SELECT
    <expression1>
  FROM
    useful_table
  WHERE
    <predicate1>
UNION
  SELECT
   <expression2>
  FROM
    useful_table
  WHERE
    <predicate2>
;

станет

SELECT DISTINCT COALESCE(u1.<expression1> , u2.<expression2> )
FROM            useful_table u1
FULL OUTER JOIN useful_table u2
ON              1 = 0
WHERE           u1.<predicate1>
                OR u2.<predicate2>

Или в вашем конкретномпример

SELECT DISTINCT COALESCE(u1.a_number, u2.a_number + 1)
FROM   useful_table u1
       FULL OUTER JOIN useful_table u2
                    ON 1 = 0
WHERE  u1.a_number = 2
        OR u2.a_number = 2 
0 голосов
/ 18 декабря 2018

Я буду использовать Union, когда больше ничего не сделаю.Я всегда обнаруживал, что объединения и конструкции case из одного запроса всегда работают лучше, чем Union.

Однако, как прокомментировал кто-то, есть время, когда строка может соответствовать двум критериям case, и это не может произойти с логикой case.

Запросы относятся к конкретной цели, но я думаю, что будет справедливо сказать, что вы не всегда можете заменить Union.

В вашем конкретном случае использования это может.

0 голосов
/ 18 декабря 2018

Одним из решений было бы дублирование выходных строк с использованием CROSS JOIN с CONNECT BY cte.

В целом, однако, это работает при предположении, что:

  • только одинтаблица задействована
  • имеется одно WHERE предложение
  • операции, выполняемые с дублированными записями, достаточно просты для реализации на основе увеличивающегося целого числа, возвращаемого CONNECT BY cte(что все еще оставляет достаточно места для действия)

Следующий запрос действительно соответствует вашему варианту использования:

with data as (select level -1 l from dual connect by level <= 2)
select a_number + l
from useful_table, data
where a_number = 2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...