sql - 为什么我不能使用 CASE 在 ORDER BY 中引用列别名?

标签 sql tsql sql-server-2005 sql-order-by

抱歉,如果这是重复的,但我还没有找到。为什么我不能使用 SELECT 中定义的列别名来自 ORDER BY当我使用 CASE ?

考虑这个简单的查询:

SELECT NewValue=CASE WHEN Value IS NULL THEN '<Null-Value>' ELSE Value END
FROM dbo.TableA
ORDER BY CASE WHEN NewValue='<Null-Value>' THEN 1 ELSE 0 END

结果报错:

Invalid column name 'NewValue'



Here's a sql-fiddle. (用被注释掉的 ORDER BY NewValue 替换 CASE WHEN...)

我知道我可以使用 ORDER BY CASE WHEN Value IS NULL THEN 1 ELSE 0 END喜欢 here在这种情况下,但实际上查询更复杂,我希望尽可能保持其可读性。我是否必须使用子查询或 CTE,如果是这样,为什么会这样?

更新 因为 Mikael Eriksson 评论过任何与别名组合的表达式都是不允许的。所以即使这个(毫无意义的查询)也会因为同样的原因而失败:
SELECT '' As Empty
FROM dbo.TableA
ORDER BY Empty + ''

结果:

Invalid column name 'Empty'.



所以在 ORDER BY 中允许使用别名也是一个表达式但是 不是两个 .为什么,实现起来太难了?由于我主要是一名程序员,因此我将别名视为可以简单地在表达式中使用的变量。

最佳答案

这与 SQL dbms 如何解析不明确的名称有关。

我还没有在 SQL 标准中追踪这种行为,但它似乎跨平台是一致的。这就是正在发生的事情。

create table test (
  col_1 integer,
  col_2 integer
);

insert into test (col_1, col_2) values 
(1, 3), 
(2, 2), 
(3, 1);

别名“col_1”为“col_2”,并在 ORDER BY 子句中使用别名。 dbms 将 ORDER BY 中的“col_2”解析为“col_1”的别名,并按“test”.“col_1”中的值进行排序。
select col_1 as col_2
from test
order by col_2;
col_2
--
1
2
3

Again, alias "col_1" as "col_2", but use an expression in the ORDER BY clause. The dbms resolves "col_2" not as an alias for "col_1", but as the column "test"."col_2". It sorts by the values in "test"."col_2".

select col_1 as col_2
from test
order by (col_2 || '');
col_2
--
3
2
1

So in your case, your query fails because the dbms wants to resolve "NewValue" in the expression as a column name in a base table. But it's not; it's a column alias.

PostgreSQL

This behavior is documented in PostgreSQL in the section Sorting Rows. Their stated rationale is to reduce ambiguity.

Note that an output column name has to stand alone, that is, it cannot be used in an expression — for example, this is not correct:

SELECT a + b AS sum, c FROM table1 ORDER BY sum + c;          -- wrong

This restriction is made to reduce ambiguity. There is still ambiguity if an ORDER BY item is a simple name that could match either an output column name or a column from the table expression. The output column is used in such cases. This would only cause confusion if you use AS to rename an output column to match some other table column's name.



SQL Server 2008 中的文档错误

关于 aliases in the ORDER BY clause 的一个稍微不同的问题.

If column names are aliased in the SELECT list, only the alias name can be used in the ORDER BY clause.



除非我的咖啡因摄入不足,否则这根本不是真的。此语句在 SQL Server 2008 和 SQL Server 2012 中均按 "test"."col_1"排序。
select col_1 as col_2
from test
order by col_1;

关于sql - 为什么我不能使用 CASE 在 ORDER BY 中引用列别名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25763920/

相关文章:

java - 如何将日期和时间转换为时间戳

sql-server - 删除周围约束

SQL Server 相当于 ORACLE INSTR

sql - 如果表不存在则创建

Sql Server 相当于 COUNTIF 聚合函数

sql - 如何实现数据库的每个用户 View ?

sql - 获取每组的前 1 行

MySQL子查询和连接3个表

sql-server - TSQL:全局脚本变量?

sql - 临时表列上的唯一性是否会创建索引?