Sql Union All * with *“distinct”

问题描述 投票:33回答:10

UNION连接两个结果并删除重复项,而UNION ALL不删除重复项。 UNION还对最终输出进行排序。

我想要的是没有重复且没有排序的UNION ALL。那可能吗?

这样做的原因是我希望第一个查询的结果位于最终结果之上,而第二个查询位于底部。 (并且每个分类就好像它们单独运行一样)

sql union distinct union-all
10个回答
47
投票

我注意到这个问题得到了很多观点,所以我首先要提出一个你没有问过的问题!

关于标题。要实现“Sql Union All with”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  

-1
投票

你可以做这样的事情。

Select distinct name from  (SELECT r.name FROM outsider_role_mapping orm1 
    union all
SELECT r.name FROM user_role_mapping orm2
) tmp;

10
投票

“UNION也对最终输出进行排序” - 仅作为实现工件。绝不保证执行排序,如果需要特定的排序顺序,则应使用ORDER BY子句指定它。否则,输出顺序是服务器提供的最方便的输出顺序。

因此,您对执行UNION ALL但删除重复项的函数的请求很容易 - 它被称为UNION


从您的澄清中,您似乎也相信UNION ALL将在后续查询结果之前返回第一个查询的所有结果。这也不能保证。同样,实现特定顺序的唯一方法是使用ORDER BY子句指定它。


3
投票
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
投票

考虑这些表(标准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,排序表Bcol降序然后联合两者,删除重复,保留联盟之前的顺序并将表A结果留在“顶部”与表“B”在“底部”例如(pesudo代码)

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

当然,这在SQL中不起作用,因为只能有一个ORDER BY子句,它只能应用于顶级表表达式(或者SELECT查询的输出被称为;我将其称为“结果集” )。

要解决的第一件事是两个表之间的交集,在这种情况下,值为456。需要在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;

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

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

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
投票

我假设你的表分别是table1和table2,你的解决方案是;

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

-1
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.