如果语句包含UNION运算符,那么ORDER BY项必须出现在选择列表中吗?

时间:2012-11-22 09:31:56

标签: sql-server

一个sql脚本,它在生产服务器上运行了很长时间, 但最近系统报告“ORDER BY项目必须出现在选择列表中,如果 语句包含UNION运算符“

奇怪的是,sql脚本仍然可以在我的测试服务器中运行。所以我没有 知道我做的任何修改是否可以在生产中正确运行。

SELECT '' as value ,'Outstanding' as text , 0 as disp_order
union
select a.buyer_status_code AS value , a.buyer_status_name AS text ,a.disp_order
FROM   rfq_buyer_status_v a WITH (NOLOCK)
ORDER BY a.disp_order

2 个答案:

答案 0 :(得分:22)

试试这个:

select * from 
(
SELECT '' as value ,'Outstanding' as text , 0 as disp_order
union
select a.buyer_status_code AS value , a.buyer_status_name AS text ,a.disp_order
FROM   rfq_buyer_status_v a WITH (NOLOCK)
) t

ORDER BY t.disp_order

答案 1 :(得分:18)

SQL Server按照以下阶段的顺序解析查询:

FROM - >在哪里 - > GROUP BY - > HAVING - >选择 - >订购

每个阶段作为输入在一个或多个表上运行,并返回虚拟表作为输出。 一个阶段的输出表被视为下一阶段的输入。这与产生关系的关系的操作是一致的。如果指定了ORDER BY,则为结果 不是关系。

在早期阶段定义的任何别名都可以在其后的阶段看到,但反之亦然。

e.g。

以下查询没问题

SELECT [Col_1], [Col_2] 
FROM Table_A AS A 
WHERE A.[Col_1] > 0
ORDER BY A.[Col_2]; 

虽然这个不起作用

SELECT [Col_1] AS C1, [Col_2] AS C2 
FROM Table_A 
WHERE C1 > 0
ORDER BY C2; 

现在, UNION集合运算符统一了两个输入查询的结果。作为集合运算符,UNION具有隐含的DISTINCT属性,这意味着它不会返回重复的行。

如果在查询中使用了UNION,它会将两个集合合为一个,并且ORDER BY将对组合集生效,而不仅仅在SELECT ... FROM ... dataset上生效。 原因是ORDER BY是队列中最弱的(或最后一个),它'捕获全部'

在查询的第一行,你给了一个名为'disp_order'的别名,没关系。在UNION运算符之后,您从表'rfq_buyer_status_v'查询了一个数据集,其中包含一个名为'disp_order'的列,这也是完全可以接受的。问题来自ORDER BY之后。

由于您还为表提供了别名,即“a”,ORDER BY a.disp_order表示限制对部分合并数据集的排序操作,该操作与“全部捕获”活动冲突。

解决方案是删除'a'。在ORDER BY子句之后。您可以这样做的原因是您给了0别名'disp_order',它与表rfq_buyer_status_v中的列名相同。那么在这种情况下,我看不到表格别名的任何值......

SELECT '' AS value ,'Outstanding' AS text , 0 AS disp_order
UNION 
SELECT a.buyer_status_code AS value , a.buyer_status_name AS text ,a.disp_order
FROM   rfq_buyer_status_v a WITH (NOLOCK)
ORDER BY disp_order

编写查询的另一种方法是

SELECT ''            AS value ,
       'Outstanding' AS text  , 
       0             AS ABC
UNION 
SELECT buyer_status_code AS value , 
       buyer_status_name AS text ,
       disp_order        AS ABC
FROM   rfq_buyer_status_v 
    WITH (NOLOCK)
ORDER BY ABC

第二个为disp_order列提供了一个完全不同的别名,使其易于阅读,并减少了在查看代码时感到困惑的可能性。