UNION
2つの結果を結合して重複を削除しますが、重複UNION ALL
は削除しません。
UNION
また、最終出力を並べ替えます。
私が欲しいのは、UNION ALL
重複や並べ替えがないことです。それは可能ですか?
これは、最初のクエリの結果を最終結果の上に置き、2番目のクエリを一番下に配置する(そしてそれぞれが個別に実行されるかのように並べ替える)ためです。
この質問は非常に多くの意見を集めていることに気付いたので、最初にあなたが尋ねなかった質問に取り組みます!
タイトルについて。「SQLUnionAllwith “ distinct”」を実現するには、単に。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
あなたの説明から、あなたはまた、aが後続のクエリの結果の前に最初のクエリからのすべての結果を返すと信じているように見えます。これも保証されません。繰り返しますが、特定の順序を実現する唯一の方法は、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
降順で並べ替えてから2つを結合し、重複を削除し、結合前の順序を保持し、テーブルのA
結果を「上」に残し、テーブルB
を「下」に残すことです。例:(疑似コード)
(
SELECT *
FROM A
ORDER
BY col
)
UNION
(
SELECT *
FROM B
ORDER
BY col DESC
);
もちろん、これはSQLでは機能しません。これは、ORDER BY
句が1つしかなく、最上位のテーブル式(または、SELECT
クエリの出力として知られているもの、つまり「結果セット」)にのみ適用できるためです。
最初に対処するのは、2つのテーブル(この場合は値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 *, 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
句を除いて、並べ替え順序は任意であり、保証されません。
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
これを試して:
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
私はあなたのテーブルがそれぞれ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;