如果该语句包含UNION,INTERSECT或EXCEPT运算符(变量),则ORDER BY项目必须出现在选择列表中

时间:2018-09-24 11:22:54

标签: sql sql-server sql-server-2017

我已经阅读了所有可以找到的与该错误有关的问题,但它们并没有完全描述这种情况。在其他情况下,人们正在做这样的事情,例如按以下顺序仅引用一个别名表(从联合的一侧)-我理解为什么SQLS在我阅读的所有其他问题中都抱怨这个特殊错误。 / p>

我看不到为什么SQL Server对此order by产生问题;顺序中提到的唯一列绝对是选择结果集的成员:

--example data:
-- a,b,c
-- 1, ,2
--  ,3,5

SELECT    1 AS a, null AS b, 2 AS c INTO #tmp
UNION
SELECT null AS a,    3 AS b, 5 AS c 

--let's call it a lame version of a rollup
SELECT * FROM #tmp            --detail rows
UNION ALL
SELECT a, b, SUM(c) FROM #tmp --summary row
GROUP BY a, b

--the problem
ORDER BY COALESCE(a, b);

DROP TABLE #tmp;

结果集包含列ab,我看不出模棱两可。即使对所有内容进行别名(不同)也无济于事:

SELECT t.a AS z, t.b AS y, t.c FROM #tmp t
UNION ALL
SELECT u.a AS z, u.b AS y, SUM(c) AS c FROM #tmp u
GROUP BY u.a, u.b
ORDER BY COALESCE(z, y);

实际上,奇怪的是,SQL Server似乎抱怨更多:

Msg 207, Level 16, State 1, Line 6
Invalid column name 'z'.
Msg 207, Level 16, State 1, Line 6
Invalid column name 'z'.           --why complain twice?
Msg 207, Level 16, State 1, Line 6
Invalid column name 'y'.
Msg 104, Level 16, State 1, Line 6
ORDER BY items must appear in the select list if the statement contains a UNION, INTERSECT or EXCEPT operator.

唯一起作用的是将其包装为另一个选择:

SELECT * FROM(
  SELECT * FROM #tmp
  UNION ALL
  SELECT a, b, SUM(c) AS c FROM #tmp
  GROUP BY u.a, u.b
) a
ORDER BY COALESCE(a, b);

SELECT * FROM(
  SELECT t.a AS z, t.b AS y, t.c FROM #tmp t
  UNION ALL
  SELECT u.a AS z, u.b AS y, SUM(c) AS c FROM #tmp u
  GROUP BY u.a, u.b
) z
ORDER BY COALESCE(z, y);

从概念上讲,我认为这是SQL Server在处理order by之前仍要处理其结果集的原因。那有什么用?

1 个答案:

答案 0 :(得分:3)

根据HoneyBadger的注解,似乎必须确实将SQLS用作错误消息的面值,而不是假设它从联合查询中构建结果集,并以在前导select中指定给列的名称作为别名。然后订购。

这个...

SELECT a, b, COALESCE(a,b) FROM t
UNION ALL
SELECT a, b, COALESCE(a,b) FROM u
ORDER BY COALESCE(a,b)

...有效,大概是因为它直接在选择列表中指定了COALESCE(a,b)以及ORDER BY

这个...

SELECT * FROM(
  SELECT a, b FROM t
  UNION ALL
  SELECT a, b FROM u
)z
ORDER BY COALESCE(a,b)

...有效,大概是因为正在排序的查询不包含UNION

使用无效表格来自其他数据库的结果的有趣混合:

Oracle:

  

ORA-01785:ORDER BY项目必须为SELECT列表表达式的编号

PostGres:

  

错误:无效的UNION / INTERSECT / EXCEPT ORDER BY子句详细信息:只能使用结果列名称,不能使用表达式或函数。提示:将表达式/函数添加到每个SELECT中,或将UNION移入FROM子句

MySQL:

  

(有效)