很抱歉,如果这个重复,但我还没找到。当我使用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
结果是错误:
无效的列名称'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 + ''
结果:
无效的列名称“空”。
因此,ORDER BY
中的别名和表达式都允许使用别名,但不是。为什么,实施起来太难了?因为我主要是程序员,所以我认为别名是变量,可以简单地用在表达式中。
答案 0 :(得分:6)
这与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中的文档错误
与aliases in the ORDER BY clause相关的略微不同的问题。
如果列名在SELECT列表中有别名,则只能在ORDER BY子句中使用别名。
除非我的咖啡因含量不足,否则这根本不是真的。此语句按SQL Server 2008和SQL Server 2012中的“test”。“col_1”进行排序。
select col_1 as col_2
from test
order by col_1;
答案 1 :(得分:0)
这个限制似乎与另一个限制有关,其中“列别名不能在同一个 SELECT
列表中被引用”。例如,这个查询:
SELECT Col1 AS ColAlias1 FROM T ORDER BY ColAlias1
可以翻译成:
SELECT Col1 AS ColAlias1 FROM T ORDER BY 1
这是一个合法的查询。但是这个查询:
SELECT Col1 AS ColAlias1 FROM T ORDER BY ColAlias1 + ' '
应该翻译成:
SELECT Col1 AS ColAlias1, ColAlias1 + ' ' FROM T ORDER BY 2
哪个会引发错误:
<块引用>“字段列表”中的未知列“ColAlias1”
最后,这些似乎是因为 SQL 标准行为,而不是在实现中是不可能的。 更多信息请访问:Here
注意:最后一个查询可以由 MS Access
执行而不会出错,但会使用 SQL Server
引发上述错误。
答案 2 :(得分:-1)
您可以尝试以下方式:
select NewValue from (
SELECT (CASE WHEN Value IS NULL THEN '<Null-Value>' ELSE Value END ) as NewValue,
( CASE WHEN NewValue='<Null-Value>' THEN 1 ELSE 0 END) as ValOrder
FROM dbo.TableA
GROUP BY Value
) t
ORDER BY ValOrder