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

2024-01-06

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

我不明白为什么 SQL Server 对此有疑问order by; order by 中提到的唯一列肯定是结果集 select 的成员:

--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;

结果集包含列a and b,我看不出有任何歧义。即使对所有内容(以不同方式)使用别名也无济于事:

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无论如何..那么什么给呢?


根据HoneyBadger的注释,似乎人们实际上必须只在错误消息的表面值上采用SQLS,而不是假设它从联合查询构建结果集,并使用前导选择中给定列的名称作为别名,然后进行排序..

This...

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 中

This...

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 列表表达式的编号

邮政格雷斯:

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

MySQL:

(works)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果语句包含 UNION、INTERSECT 或 EXCEPT 运算符(变体),则 ORDER BY 项必须出现在选择列表中 的相关文章

随机推荐