web-dev-qa-db-ja.com

Sql Union All * with * "distinct"

UNIONは2つの結果を結合して重複を削除しますが、UNION ALLは重複を削除しません。 UNIONは最終出力もソートします。

私が欲しいのは、重複やソートのないUNION ALLです。それは可能ですか?

その理由は、最初のクエリの結果が最終結果の上になり、2番目のクエリの結果が最後になるようにするためです。 (それぞれが個別に実行されるかのようにソートされます)

34
hightow

この質問には非常に多くの意見がありますので、まず質問に答えますdid n't ask!

タイトルについて。 「Sql Union Allwith“ distinct”」を達成するには、単にUNION ALL with 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  
47
Martin Smith

「UNIONは最終出力もソートします」-実装アーティファクトとしてのみ。 無意味によるソートの実行が保証されています。特定のソート順が必要な場合は、ORDER BY句で指定する必要があります。それ以外の場合、出力順序はサーバーが提供するのに最も便利なものです。

そのため、UNION ALLを実行するが重複を削除する関数のリクエストは簡単です。これはUNIONと呼ばれます。


説明から、UNION ALLが最初のクエリの結果をすべて返し、その後のクエリの結果を返すと信じているようにも見えます。これはalso保証されていません。繰り返しますが、特定の順序を実現する唯一の方法は、ORDER BY句を使用して指定することです。

10
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句、ソート順は任意であり、保証されません。

3
onedaywhen

次の表を考慮してください(標準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)
     ), ...
_

望ましい効果は、テーブルAcolでソートし、テーブルBcolでソートし、降順で2つを結合し、重複を削除し、結合前の順序を保持して終了することです。テーブルAは "top"に、テーブルBは "bottom"に、例えば(擬似コード)

_(
 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の「上」および「下」の注には推論的な意味はなく、テーブル(結果セット以外)には固有の順序はありません。また、(長い話を短くするために)UNIONは含意によって重複行を削除し、_ORDER BY_の前に適用する必要があることを考慮してください。結論は、各テーブルのソート順は、ソート順列を公開することによって明示的に定義する必要があるということですbefore unionedこのために、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;
_
3
onedaywhen

これを試して:

  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
1
Divya Agrawal
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
1
Mikael Eriksson

ソートは重複を排除するために使用され、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
0
Rowland Shaw

私はあなたのテーブルがそれぞれtable1とtable2であり、あなたのソリューションがそうであると仮定します;

(select * from table1 MINUS select * from table2)
UNION ALL
(select * from table2 MINUS select * from table1)
0
dursun