Sql Union All * с * "отличным"
UNION объединяет два результата и удаляет дубликаты, а UNION ALL не удаляет дубликаты. UNION также сортирует окончательный результат.
Что я хочу, так это СОЮЗ ВСЕХ без дубликатов и без сортировки. Это возможно?
Причина этого заключается в том, что я хочу, чтобы результат первого запроса был сверху окончательного результата, а второй запрос - внизу. (И каждый отсортирован так, как будто они бегут индивидуально)
8 ответов
Я заметил, что этот вопрос получил довольно много просмотров, поэтому сначала я отвечу на вопрос, который вы не задавали!
По поводу названия. Чтобы добиться "Sql Union All с " отличным "", просто замените UNION ALL
с UNION
, Это приводит к удалению дубликатов.
Для вашего конкретного вопроса, учитывая пояснение "Первый запрос должен иметь" приоритет ", поэтому дубликаты должны быть удалены снизу", вы можете использовать
SELECT col1,
col2,
MIN(grp) AS source_group
FROM (SELECT 1 AS grp,
col1,
col2
FROM t1
UNION ALL
SELECT 2 AS grp,
col1,
col2
FROM t2) AS t
GROUP BY col1,
col2
ORDER BY MIN(grp),
col1
"UNION также сортирует окончательный результат" - только как артефакт реализации. Это ни в коем случае не гарантирует выполнение сортировки, и если вам нужен определенный порядок сортировки, вы должны указать его с помощью ORDER BY
пункт. В противном случае порядок вывода является наиболее удобным для сервера.
Таким образом, ваш запрос на функцию, которая выполняет UNION ALL
но удалить дубликаты легко - это называется UNION
,
Судя по вашим разъяснениям, вы также считаете, что UNION ALL
вернет все результаты первого запроса до результатов последующих запросов. Это также не гарантируется. Опять же, единственный способ достичь определенного порядка - указать его с помощью ORDER BY
пункт.
SELECT *, 1 AS sort_order
FROM table1
EXCEPT
SELECT *, 1 AS sort_order
FROM table2
UNION
SELECT *, 1 AS sort_order
FROM table1
INTERSECT
SELECT *, 1 AS sort_order
FROM table2
UNION
SELECT *, 2 AS sort_order
FROM table2
EXCEPT
SELECT *, 2 AS sort_order
FROM table1
ORDER BY sort_order;
Но реальный ответ: кроме ORDER BY
оговорка, порядок сортировки будет произвольным и не гарантируется.
Рассмотрим эти таблицы (стандартный код SQL, работает на SQL Server 2008):
WITH A
AS
(
SELECT *
FROM (
VALUES (1),
(2),
(3),
(4),
(5),
(6)
) AS T (col)
),
B
AS
(
SELECT *
FROM (
VALUES (9),
(8),
(7),
(6),
(5),
(4)
) AS T (col)
), ...
Желаемый эффект это сортировка таблицы A
от col
по возрастанию, сортировка таблицы B
от col
спуск, затем объединение двух, удаление дубликатов, сохранение порядка перед объединением и выход из таблицы A
результаты на "вершине" с таблицей B
в нижней части, например, (псевдокод)
(
SELECT *
FROM A
ORDER
BY col
)
UNION
(
SELECT *
FROM B
ORDER
BY col DESC
);
Конечно, это не будет работать в SQL, потому что может быть только один ORDER BY
предложение, и оно может быть применено только к выражению таблицы верхнего уровня (или к какому-либо выводу SELECT
запрос известен как; Я называю это "набор результатов").
Первое, на что нужно обратить внимание - это пересечение двух таблиц, в данном случае значений 4
, 5
а также 6
, Способ сортировки пересечения должен быть указан в коде SQL, поэтому желательно, чтобы конструктор также указывал это! (т.е. человек, задающий вопрос, в данном случае).
В этом случае может показаться, что пересечение ("дубликаты") должно быть отсортировано в результатах для таблицы A. Следовательно, отсортированный набор результатов должен выглядеть следующим образом:
VALUES (1), -- A including intersection, ascending
(2), -- A including intersection, ascending
(3), -- A including intersection, ascending
(4), -- A including intersection, ascending
(5), -- A including intersection, ascending
(6), -- A including intersection, ascending
(9), -- B only, descending
(8), -- B only, descending
(7), -- B only, descending
Обратите внимание, что в SQL "top" и "bottom" не имеют никакого промежуточного значения, а таблица (кроме результирующего набора) не имеет внутреннего порядка. Также (короче говоря) учтите, что UNION
удаляет повторяющиеся строки косвенно и должен быть применен до ORDER BY
, Вывод должен состоять в том, что порядок сортировки каждой таблицы должен быть явно определен путем выставления столбцов порядка сортировки перед объединением. Для этого мы можем использовать ROW_NUMBER()
оконная функция, например
...
A_ranked
AS
(
SELECT col,
ROW_NUMBER() OVER (ORDER BY col) AS sort_order_1
FROM A -- include the intersection
),
B_ranked
AS
(
SELECT *,
ROW_NUMBER() OVER (ORDER BY col DESC) AS sort_order_1
FROM B
WHERE NOT EXISTS ( -- exclude the intersection
SELECT *
FROM A
WHERE A.col = B.col
)
)
SELECT *, 1 AS sort_order_0
FROM A_ranked
UNION
SELECT *, 2 AS sort_order_0
FROM B_ranked
ORDER BY sort_order_0, sort_order_1;
Попробуй это:
SELECT DISTINCT * FROM (
SELECT column1, column2 FROM Table1
UNION ALL
SELECT column1, column2 FROM Table2
UNION ALL
SELECT column1, column2 FROM Table3
) X ORDER BY Column1
select T.Col1, T.Col2, T.Sort
from
(
select T.Col1,
T.Col2,
T.Sort,
rank() over(partition by T.Col1, T.Col2 order by T.Sort) as rn
from
(
select Col1, Col2, 1 as Sort
from Table1
union all
select Col1, Col2, 2
from Table2
) as T
) as T
where T.rn = 1
order by T.Sort
Я предполагаю, что ваши таблицы - table1 и table2 соответственно, а ваше решение -;
(select * from table1 MINUS select * from table2)
UNION ALL
(select * from table2 MINUS select * from table1)
Сортировка используется для устранения дубликатов и является неявной для DISTINCT
а также UNION
запросы (но не UNION ALL
) - вы все равно можете указать столбцы, по которым вы хотите упорядочить их, если вам нужно их отсортировать по определенным столбцам.
Например, если вы хотите отсортировать по результирующим наборам, вы можете ввести дополнительный столбец и отсортировать по первому:
SELECT foo, bar, 1 as ResultSet
FROM Foo
WHERE bar = 1
UNION
SELECT foo, bar, 2 as ResultSet
FROM Foo
WHERE bar = 3
UNION
SELECT foo, bar, 3 as ResultSet
FROM Foo
WHERE bar = 2
ORDER BY ResultSet
1,1:
select 1 from dual
union all select 1 from dual
1:
select 1 from dual
union select 1 from dual
Вы можете сделать что-то вроде этого.
Select distinct name from (SELECT r.name FROM outsider_role_mapping orm1
union all
SELECT r.name FROM user_role_mapping orm2
) tmp;