如何在不排序的情况下执行UNION? (SQL)

发布于 2024-12-06 15:00:56 字数 225 浏览 1 评论 0原文

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

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

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

UNION joins two results and remove duplicates, while UNION ALL does not remove duplicates.
UNION also sort the final output.

What I want is the UNION ALL without duplicates and without the sort. Is that possible?

The reason for this is that I want the result of the first query to be on top of the final result, and the second query at the bottom (and each sorted as if they where run individually).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

情域 2024-12-13 15:00:56

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

关于标题。要实现“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  

I notice this question gets quite a lot of views so I'll first address a question you didn't ask!

Regarding the title. To achieve a "Sql Union All with “distinct”" then simply replace UNION ALL with UNION. This has the effect of removing duplicates.

For your specific question, given the clarification "The first query should have "priority", so duplicates should be removed from bottom" you can use

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  
帅气称霸 2024-12-13 15:00:56

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

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


根据您的澄清,您似乎还认为 UNION ALL 会先返回第一个查询的所有结果,然后再返回后续查询的结果。这无法保证。同样,实现特定顺序的唯一方法是使用 ORDER BY 子句指定它。

"UNION also sort the final output" - only as an implementation artifact. It is by no means guaranteed to perform the sort, and if you need a particular sort order, you should specify it with an ORDER BY clause. Otherwise, the output order is whatever is most convenient for the server to provide.

As such, your request for a function that performs a UNION ALL but that removes duplicates is easy - it's called UNION.


From your clarification, you also appear to believe that a UNION ALL will return all of the results from the first query before the results of the subsequent queries. This is also not guaranteed. Again, the only way to achieve a particular order is to specify it using an ORDER BY clause.

浮萍、无处依 2024-12-13 15:00:56
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 子句之外,排序顺序是任意的且无法保证。

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;

But the real answer is: other than the ORDER BY clause, the sort order will by arbitrary and not guaranteed.

稚气少女 2024-12-13 15:00:56

考虑这些表(标准 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 升序对表 A 进行排序,对表 B 进行排序code> 按 col 降序排列,然后将两者合并,删除重复项,保留合并之前的顺序,并将表 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;

Consider these tables (Standard SQL code, runs on 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)
     ), ...

The desired effect is this to sort table A by col ascending, sort table B by col descending then unioning the two, removing duplicates, retaining order before the union and leaving table A results on the "top" with table B on the "bottom" e.g. (pesudo code)

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

Of course, this won't work in SQL because there can only be one ORDER BY clause and it can only be applied to the top level table expression (or whatever the output of a SELECT query is known as; I call it the "resultset").

The first thing to address is the intersection between the two tables, in this case the values 4, 5 and 6. How the intersection should be sorted needs to be specified in SQL code, therefore it is desirable that the designer specifies this too! (i.e. the person asking the question, in this case).

The implication in this case would seem to be that the intersection ("duplicates") should be sorted within the results for table A. Therefore, the sorted resultset should look like this:

      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 

Note in SQL "top" and "bottom" has no inferent meaning and a table (other than a resultset) has no inherent ordering. Also (to cut a long story short) consider that UNION removes duplicate rows by implication and must be applied before ORDER BY. The conclusion has to be that each table's sort order must be explicitly defined by exposing a sort order column(s) before being unioned. For this we can use the ROW_NUMBER() windowed function e.g.

     ...
     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;
ぃ弥猫深巷。 2024-12-13 15:00:56
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
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
奢望 2024-12-13 15:00:56

试试这个:

  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

Try this:

  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
寂寞笑我太脆弱 2024-12-13 15:00:56

该排序用于消除重复项,并且对于 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

The sort is used to eliminate the duplicates, and is implicit for DISTINCT and UNION queries (but not UNION ALL) - you could still specify the columns you'd prefer to order by if you need them sorted by specific columns.

For example, if you wanted to sort by the result sets, you could introduce an additional column, and sort by that first:

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
烟酒忠诚 2024-12-13 15:00:56

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

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

I assume your tables are table1 and table2 respectively,
and your solution is;

(select * from table1 MINUS select * from table2)
UNION ALL
(select * from table2 MINUS select * from table1)
z祗昰~ 2024-12-13 15:00:56

1,1:
<代码>
从双选 1
union all 从对偶中选择 1

1:
<代码>
从双选 1
并从对偶中选择 1

1,1:

select 1 from dual
union all select 1 from dual

1:

select 1 from dual
union select 1 from dual

木緿 2024-12-13 15:00:56

你可以做这样的事情。

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

You can do something like this.

Select distinct name from  (SELECT r.name FROM outsider_role_mapping orm1 
    union all
SELECT r.name FROM user_role_mapping orm2
) tmp;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文