UNION
连接两个结果并删除重复项,同时UNION ALL
不删除重复项。
UNION
还对最终输出进行排序。
我想要的是UNION ALL
没有重复和没有排序。那可能吗?
这样做的原因是我希望第一个查询的结果位于最终结果之上,而第二个查询位于底部(并且每个查询都像单独运行一样排序)。
我注意到这个问题得到了很多观点,所以我将首先解决一个你没有问的问题!
关于标题。要实现“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
“UNION 也对最终输出进行排序” - 仅作为实现工件。绝对不能保证执行排序,如果您需要特定的排序顺序,则应使用ORDER BY
子句指定它。否则,输出顺序是服务器提供的最方便的顺序。
因此,您对执行 aUNION ALL
但删除重复项的函数的请求很容易 - 它被称为UNION
.
根据您的说明,您似乎还相信 aUNION ALL
将在后续查询的结果之前返回第一个查询的所有结果。这也不能保证。同样,实现特定顺序的唯一方法是使用ORDER BY
子句指定它。
考虑这些表(标准 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 代码中指定,因此希望设计者也指定这一点!(在这种情况下,即提出问题的人)。5
6
在这种情况下,似乎应该在表 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;
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 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 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
排序用于消除重复,并且对于DISTINCT
和UNION
查询是隐式的(但不是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
我假设你的表分别是 table1 和 table2,你的解决方案是;
(select * from table1 MINUS select * from table2)
UNION ALL
(select * from table2 MINUS select * from table1)
1,1:
select 1 from dual
union all select 1 from dual
1:
select 1 from dual
union select 1 from dual
你可以做这样的事情。
Select distinct name from (SELECT r.name FROM outsider_role_mapping orm1
union all
SELECT r.name FROM user_role_mapping orm2
) tmp;