2011-09-26 40 views
18

UNION加入兩個結果並刪除重複項,而UNION ALL不刪除重複項。 UNION也排序最終輸出。Sql Union所有*帶*「不同」

我想要的是沒有重複和沒有排序的UNION ALL。那可能嗎?

這樣做的原因是我希望第一個查詢的結果位於最終結果的頂部,而第二個查詢的結果位於底部。 (以及每個分類就好像他們在那裏單獨運行)

+0

什麼SQL供應商是這樣嗎?我不認爲該標準要求'UNION ALL'排序任何東西 - 其實事實上,它不排序,通常是什麼使得它比普通'UNION' – Romain

+0

@MikaelEriksson一個更好的選擇:這是什麼OP說(儘管是在一個混亂的秩序)。他想做一個聯盟,但沒有隱含的排序。 – mwan

+0

@mwan - 你說得對。我誤解了這個問題。 –

回答

26

我注意到這個問題得到了相當多的意見,讓我我會先問你一個問題沒問問!

關於標題。爲了實現「Sql 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 
+0

+1暴露的排序順序給調用者是很好的做法,無論如何被刪除。 – onedaywhen

+0

@onedaywhen - 感謝您的編輯。錯過了這個問題。 –

+0

如果消除單個查詢中的重複內容是所有必需的,但這種方法可行,但如果還需要刪除兩個查詢中的重複內容,則不適用。 –

0

的排序是用來消除重複,並且是隱含的DISTINCTUNION查詢(但不是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

我假設你的表分別爲表1和表2, 和你的解決方案是;

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

這會不會排除有重複的所有行?我寧願他們想要刪除重複的東西! – onedaywhen

+0

看到我的答案進行了更正(我使用的是標準SQL的「EXCEPT」而不是Oracle的「MINUS」,但這不是修正:) – onedaywhen

10

「UNION還對最終輸出進行排序」 - 僅作爲實現工件。它是由決不意味着保證執行排序,如果你需要一個特定的排序順序,你應該指定它與ORDER BY子句。否則,輸出順序是服務器提供的最方便的。

因此,您對執行UNION ALL但刪除重複項的函數的請求很容易 - 它被稱爲UNION


從你澄清,你似乎也相信UNION ALL將在隨後的查詢結果返回之前所有的結果從第一查詢。這是不能保證。同樣,實現特定順序的唯一方法是使用ORDER BY子句來指定它。

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條款等,排序順序將由任意的,不能保證。

1
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 
2

考慮這些表(標準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) 
    ), ... 

所需的效果是這樣的由col升序排序表B通過col排序表A,降則unioning二,刪除重複,工會之前保持秩序,在「頂」上的「底部」,例如與表B離開表A結果(04-0030-03代碼)

(
SELECT * 
    FROM A 
    ORDER 
    BY col 
) 
UNION 
(
SELECT * 
    FROM B 
    ORDER 
    BY col DESC 
); 

當然,這不會在SQL工作,因爲只能有一個ORDER BY子句和它只能被應用於頂層表表達式(或任何一個SELECT查詢的輸出被稱爲;我稱之爲「結果集」)。

首先要解決的是兩個表格之間的交集,在這種情況下,值爲4,56。如何對交叉點進行排序需要在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之前應用。結論顯然是因爲每個表的排序順序必須明確通過暴露排序順序列(S)是聯合在一起之前定義。爲此,我們可以使用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; 
0

1,1: select 1 from dual union all select 1 from dual 1: select 1 from dual union select 1 from dual

+2

儘管此代碼片段是受歡迎的,並且可能會提供一些幫助,如果它包含* how *的解釋](// meta.stackexchange.com/q/114762),則說明問題。沒有這些,你的答案就沒有什麼教育價值了 - 記住,你正在爲將來的讀者回答這個問題,而不僅僅是現在問的人!請編輯您的答案以添加解釋,並指出適用的限制和假設。 –