如何在 SQL 中使用 union 排序?

Posted

技术标签:

【中文标题】如何在 SQL 中使用 union 排序?【英文标题】:How to order by with union in SQL? 【发布时间】:2011-06-10 14:11:30 【问题描述】:

当数据来自多个选择并合并在一起时,是否可以排序?比如

Select id,name,age
From Student
Where age < 15
Union
Select id,name,age
From Student
Where Name like "%a%"

如何按名称排序此查询?

我试过了

Select id,name,age
From Student
Where age < 15 or name like "%a%"
Order by name

但这不起作用。

【问题讨论】:

如果你在联合查询中有相同的列,那么最后按你的列名排序。 【参考方案1】:
Select id,name,age
from
(
   Select id,name,age
   From Student
   Where age < 15
  Union
   Select id,name,age
   From Student
   Where Name like "%a%"
) results
order by name

【讨论】:

正如 bernd_k 指出的,根据定义,组成 UNION 的各个 SELECT 不允许包含 ORDER BY 子句。唯一允许的 ORDER BY 子句位于 UNION 的末尾,它适用于整个 UNION,使 xxx UNION yyy ORDER BY zzz 等同于 (xxx UNION yyy) ORDER BY zzz【参考方案2】:

随便写

Select id,name,age
From Student
Where age < 15
Union
Select id,name,age
From Student
Where Name like "%a%"
Order by name

order by 应用于完整的结果集

【讨论】:

如果我希望仅在 UNION 的顶部应用排序怎么办? @marifrahman 看我的回答***.com/a/43855496/2340825 @marifrahman 很抱歉挖掘了一个老话题,但它可能对其他人有所帮助。如果您希望将 ORDER BY 应用于 UNION 的第一部分,请用括号保护此 SELECT。【参考方案3】:

其他两个答案都是正确的,但我认为值得注意的是,我被卡住的地方没有意识到您需要按别名排序并确保两个选择的别名相同...所以

select 'foo'
union
select item as `foo`
from myTable
order by `foo`

请注意,我在第一个选择中使用单引号,而在其他选择中使用反引号。

这将为您提供所需的排序。

【讨论】:

在第一个选择中使用单引号,在其他选择中使用反引号,您想强调什么?理想情况下,它应该是一致的。 第一个选择是文字;它是一个像“NAMES”这样的标题。第二个选择是对表的引用。因此,您的第一行将显示“NAMES”,其余行将是从表中选择的实际名称。关键是您的标题很可能与您从中选择的列的名称是相同的字符串,这是使用您想要的标签而不会在您的联合中发生冲突的解决方案。 经过一些实验,我发现 ORDER BY 子句中提到的别名必须在 SELECT 子句中提及。您不能按另一列排序。当然,如果你真的想避免返回额外的列,你可以通过将整个内容包装在 SELECT a, b, c FROM (&lt;insert union query here&gt;) AS x; 中来解决这个问题。【参考方案4】:

Order Byunion 之后应用,所以只需 在语句末尾添加order by 子句:

Select id,name,age
From Student
Where age < 15
Union
Select id,name,age
From Student
Where Name like '%a%'
Order By name

【讨论】:

【参考方案5】:

如果我希望排序仅应用于UNION 之一,如果使用UNION ALL

Select id,name,age
From Student
Where age < 15
Union all
Select id,name,age
From 
(
Select id,name,age
From Student
Where Name like "%a%"
Order by name
)

【讨论】:

【参考方案6】:

为了使排序仅适用于UNION 中的第一条语句,您可以将其放在带有UNION ALL 的子选择中(这两个在Oracle 中似乎都是必需的):

Select id,name,age FROM 
(    
 Select id,name,age
 From Student
 Where age < 15
 Order by name
)
UNION ALL
Select id,name,age
From Student
Where Name like "%a%"

或者(针对 Nicholas Carey 的评论)您可以保证顶部的 SELECT 是有序的,结果显示在底部 SELECT 的上方,如下所示:

Select id,name,age, 1 as rowOrder
From Student
Where age < 15
UNION
Select id,name,age, 2 as rowOrder
From Student
Where Name like "%a%"
Order by rowOrder, name

【讨论】:

是的。这对子选择的结果进行排序。这不会对引用该子选择的select 语句的结果进行排序。根据 SQL 标准,结果的顺序是未定义的,除非有明确的 order by 子句。您的示例中的第一个select 可能按子选择返回的顺序返回其结果,但不能保证。此外,*not* 保证整个union 的结果集的排序(标准中的相同规则)。如果你依赖订单,你最终会被咬。 @Nicholas Carey - 当我最初使用 UNION 进行测试时,它的行为如您所描述的那样不可预测,我认为 UNION ALL(至少在 Oracle 中)对于在底部上方订购顶部 SELECT 是必要的。但是我提供了一个替代方案,它可以保证正确的排序并且应该是独立于数据库的。 不适合我。使用 UNION ALL 的那个仍然无法在第一个 SELECT 内保持顺序。 第二个查询的问题是,它并没有消除重复记录。因为您添加了另一列“rowOrder”,该列可能对重复记录具有不同的值。 UNION 针对 UNION ALL 的目的丢失了。 @AmitChigadani 消除重复不是原始问题的一部分,但可以修改 WHERE 子句以确保唯一性。例如:其中 Name like "%a%" AND age >= 15【参考方案7】:

正如其他答案所述,last 之后的ORDER BY UNION 应该适用于联合加入的两个数据集。

我有两个数据集使用不同的表但相同的列。 ORDER BY 在最后一个 UNION 之后仍然没有工作。

ORDER BY 子句中使用的列使用别名就可以了。

Select Name, Address for Employee 
Union
Select Customer_Name, Address from Customer
order by customer_name;   --Won't work

解决方案是使用别名User_Name,如下所示:

Select Name as User_Name, Address for Employee 
Union
Select Customer_Name as User_Name, Address from Customer
order by User_Name; 

【讨论】:

不要在 spark SQL 中做这个把戏:mismatched input 'FOR' expecting &lt;EOF&gt;【参考方案8】:

可以用这个:

Select id,name,age
From Student
Where age < 15
Union ALL
SELECT * FROM (Select id,name,age
From Student
Where Name like "%a%")

【讨论】:

【参考方案9】:

要将 ORDER BY 或 LIMIT 子句应用于单个 SELECT,请将 SELECT 括起来并将子句放在括号内:

(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);

【讨论】:

适用于 PostgreSQL【参考方案10】:

在查询中添加一列,可以对要排序的数据进行子标识。

在下面的示例中,我使用了一个通用表表达式,选择您显示的内容,并将它们放入 CTE 上的特定组中;然后将这两个组的union 关闭到AllStudents

最终的选择将首先对AllStudents 进行排序SortIndex 列,然后然后按name,例如:

WITH Juveniles as
(
      Select 1 as [SortIndex], id,name,age From Student
      Where age < 15
),

AStudents as
(
      Select 2 as [SortIndex], id,name,age From Student
      Where Name like "%a%" 
),

AllStudents as
(
      select * from Juveniles
      union 
      select * from AStudents
)

select * from AllStudents
sort by [SortIndex], name;

总而言之,它会得到所有的学生,首先按组排序,然后按组内的名称进行子排序。

【讨论】:

【参考方案11】:

为什么不使用 TOP X?

SELECT pass1.* FROM 
 (SELECT TOP 2000000 tblA.ID, tblA.CustomerName 
  FROM TABLE_A AS tblA ORDER BY 2) AS pass1
UNION ALL 
SELECT pass2.* FROM 
  (SELECT TOP 2000000 tblB.ID, tblB.CustomerName 
   FROM TABLE_B AS tblB ORDER BY 2) AS pass2

TOP 2000000 是一个任意数字,足以捕获所有数据。根据您的要求进行调整。

【讨论】:

“前 100%”更好。 “前 100%”存在问题。见上面的链接 有趣。链接在哪里? 嗯,似乎有人删除了他们的评论。好的:***.com/questions/1393508/… 和这里 sqlshack.com/… 这与性能有关,具体取决于索引。【参考方案12】:

为了添加到旧主题,我使用了 ROW_NUMBER(使用 MS SQL)。这允许在 UNION 中进行排序(订单)。 所以使用@BATabNabber 的想法来分隔联合的每一半,@Wodin 将整个东西包装在一个选择中,我得到了:

Select Id, Name, Age from
(
Select Id, Name, Age, 1 as Mainsort
 , ROW_NUMBER() over (order by age) as RowNumber
From Student
Where Age < 15

Union

Select Id, Name, Age, 2 as Mainsort
 , ROW_NUMBER() over (Order by Name) as RowNumber
From Student
Where Name like '%a%'
) as x
Order by Mainsort, RowNumber

因此,调整或省略您想要排序的内容,并根据需要添加降序。

【讨论】:

请将代码和数据添加为文本 (using code formatting),而不是图像。图片:A)不允许我们复制粘贴代码/错误/数据进行测试; B) 不允许根据代码/错误/数据内容进行搜索;和many more reasons。除了代码格式的文本之外,只有在图像添加了一些重要的东西,而不仅仅是文本代码/错误/数据传达的内容时,才应该使用图像。

以上是关于如何在 SQL 中使用 union 排序?的主要内容,如果未能解决你的问题,请参考以下文章

SQL union all 排序问题

如何在 UNION 之间的 SQL 中放置 ORDER BY 子句

php sql 中WHERE 的条件:IN(3,2,5,8) 结果如何按IN中的顺序排序

与 UNION 一起使用时,对每个 SQL Server 查询都不起作用的排序

SQL语句:使用了union all后怎么分组排序

UNION表时如何在Bigquery中重新排列/重新排序嵌套的重复列