如何在SQL中用联合排序?


201

当数据来自多个select并将其合并在一起时,是否可以订购?如

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
如果联合查询中具有相同的列,则最后按列名下达订单。
anirban karak 2015年

Answers:


266

写就好了

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

排序依据将应用于完整的结果集


45
如果我希望仅将排序应用于UNION的顶部怎么办?
marifrahman 2015年

7
@marifrahman看到我的答案stackoverflow.com/a/43855496/2340825
BA TabNabber

2
@marifrahman很抱歉挖掘一个旧话题,但这可能会帮助其他人。如果希望将ORDER BY应用于UNION的第一部分,请用括号保护此SELECT。
Lideln Kyoku

82
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

46
正如bernd_k所指出的那样,根据定义,组成UNION的各个SELECT不允许包含ORDER BY子句。唯一允许的ORDER BY子句位于UNION的末尾,并且适用于整个UNION,xxx UNION yyy ORDER BY zzz(xxx UNION yyy) ORDER BY zzz
Nicholas Carey

39

为了使排序仅适用于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

4
是。这将对子选择的结果进行排序。这不会对select引用该子选择的语句的结果进行排序。根据SQL标准,除非有明确的order by子句,否则结果的顺序是不确定的。select在您的示例中,第一个可能会按照子选择返回的顺序返回其结果,但不能保证。此外,这并不能保证整个结果集的顺序union(与标准中的规则相同)。如果您要依靠订单,最终您将被咬。
尼古拉斯·凯里

1
@Nicholas Carey-当我最初使用UNION进行测试时,它的表现出乎您的意料,我认为UNION ALL(至少在Oracle中如此)是必要的,以便将顶部的SELECT排序在底部之上。但是,我提供了一个替代方法,可以保证正确的排序,并且应独立于数据库。
BA TabNabber

不为我工作。拥有UNION ALL的用户仍然无法在第一个之内维持订单SELECT
阿米特·奇加达尼

第二个查询的问题是,它不能消除重复的记录。因为您添加了另一列“ rowOrder”,所以对于重复记录,该列可能具有不同的值。反对UNION ALL的UNION目的丢失了。
阿米特·奇加达尼

1
@AmitChigadani消除重复不是原始问题的一部分,但是这样做可以修改WHERE子句以确保唯一性。例如:凡“%a%”之类的名称且年龄> = 15
BA TabNabber '18

12

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

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

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

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


您要在首次选择中使用单引号和在其他选择中使用反引号有什么重要意义?理想情况下,它应该是一致的。
nanosoft

第一个选择是文字。它是像“ NAMES”之类的标题。第二个选择是对表的引用。因此,您的第一行将显示“ NAMES”,其余各行将是从表中选择的实际名称。关键是您的标头很可能与您要从中选择的列的名称相同,并且这是使用所需标签而不会碰撞到并集的解决方案。
Yevgeny Simkin

2
经过一些试验,我发现必须在SELECT子句中提及ORDER BY子句中提到的别名。您无法按另一列排序。当然,SELECT a, b, c FROM (<insert union query here>) AS x;如果您确实想避免返回多余的列,则可以通过将整个内容包装在a中来解决此问题。
沃丁

11

Order By在之后应用union,因此只需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

9

如果我使用全联盟,则仅希望将排序应用于仅一个UNION:

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
)

8

如其他答案所述,LAST Union之后的“排序依据”应适用于通过union联接的两个数据集。

我当时有两个数据集,但是使用不同的表但使用相同的列。LAST Union之后的“订购依据”仍然无效。将ALIAS用于​​“ 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; 

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.