36

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

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

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

4

10 回答 10

52

我注意到这个问题得到了很多观点,所以我将首先解决一个你没有问的问题!

关于标题。要实现“Sql Union All with “distinct””,只需将其替换UNION ALLUNION. 这具有删除重复项的效果。

对于您的具体问题,鉴于“第一个查询应具有“优先级”,因此应从底部删除重复项”的说明,您可以使用

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  
于 2011-09-26T07:56:36.310 回答
11

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

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


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

于 2011-09-26T07:59:05.983 回答
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升序对表格进行排序,B通过col降序对表格进行排序,然后将两者联合,删除重复项,在联合之前保留顺序并将表格A结果留在“顶部”,表格B在“底部”,例如(伪代码)

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

当然,这在 SQL 中是行不通的,因为只能有一个ORDER BY子句,并且只能应用于顶级表表达式(或任何SELECT已知的查询输出;我称之为“结果集”)。

首先要解决的是两个表之间的交集,在本例中是值4和。交集应该如何排序需要在 SQL 代码中指定,因此希望设计者也指定这一点!(在这种情况下,即提出问题的人)。56

在这种情况下,似乎应该在表 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;
于 2011-09-26T13:11:33.597 回答
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子句之外,排序顺序将是任意的,不能保证。

于 2011-09-26T08:14:03.670 回答
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
于 2011-09-26T08:22:02.733 回答
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
于 2019-02-27T07:17:51.777 回答
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
于 2011-09-26T07:53:56.727 回答
0

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

(select * from table1 MINUS select * from table2)
UNION ALL
(select * from table2 MINUS select * from table1)
于 2011-09-26T07:57:49.273 回答
-1

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

于 2017-05-08T09:27:48.627 回答
-1

你可以做这样的事情。

Select distinct name from  (SELECT r.name FROM outsider_role_mapping orm1 
    union all
SELECT r.name FROM user_role_mapping orm2
) tmp;
于 2019-01-04T14:09:01.723 回答