2011-09-26 35 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),则说明问题。没有这些,你的答案就没有什么教育价值了 - 记住,你正在为将来的读者回答这个问题,而不仅仅是现在问的人!请编辑您的答案以添加解释,并指出适用的限制和假设。 –