小编典典

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

sql

抱歉,如果这是重复的,但是我还没有找到。为什么我不能用在我的定义列别名SELECTORDER 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

结果是一个错误:

无效的列名“ NewValue”

这是一个sql小提琴。(替换ORDER BY NewValueCASE WHEN...的是麓的注释掉)

我知道我可以使用ORDER BY CASE WHEN Value IS NULL THEN 1 ELSE 0 END
这里

在这种情况下,但实际上在查询比较复杂,我想保持它尽可能地易读。我是否必须改用子查询或CTE,如果是这样,为什么呢?

*由于Mikael Eriksson注释了 任何 与别名结合使用的表达式,因此进行了 *更新
。因此,即使是这个(无意义的查询)也由于相同的原因而失败:

SELECT '' As Empty
FROM dbo.TableA
ORDER BY Empty + ''

结果:

无效的列名“ Empty”。

因此在ORDER BY和表达式中都允许使用别名,但 不能同时使用两者
。为什么,实施起来太困难了?由于我主要是程序员,因此我将别名视为可以在表达式中简单使用的变量。


阅读 229

收藏
2021-05-05

共1个答案

小编典典

这与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

同样,别名“ col_1”为“ col_2”,但在ORDER BY子句中使用表达式。dbms 不会 将“ col_2”解析为“
col_1”的别名,而是解析为“ test”。“ col_2”列。它按“ test”。“ col_2”中的值排序。

select col_1 as col_2
from test
order by (col_2 || '');



col_2
--
3
2个
1个

因此,在您的情况下,您的查询失败,因为dbms希望将表达式中的“ NewValue”解析为基表中的列名。但事实并非如此;这是列别名。

PostgreSQL的

PostgreSQL的Sorting Rows部分中记录了此行为。他们陈述的理由是减少歧义。

请注意,输出列名称必须独立存在,即不能在表达式中使用-例如,这是 正确的:

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

进行此限制是为了减少歧义。如果ORDER
BY项是一个简单名称,可以匹配输出列名称或表表达式中的列,则仍然存在歧义。在这种情况下使用输出列。仅当您使用AS重命名输出列以使其与其他表列的名称匹配时,这才会引起混淆。

SQL Server 2008中的文档错误

一个 稍微 不同的问题,相对于在ORDER BY子句中的别名

如果在SELECT列表中为列名加上别名,则只能在ORDER BY子句中使用别名。

除非我没有足够的咖啡因,否则那不是真的。在SQL Server 2008和SQL Server 2012中,此语句均按“测试”。“ col_1”排序。

select col_1 as col_2
from test
order by col_1;
2021-05-05