2014-09-10 20 views
10

对不起,如果这是重复的,但我还没有找到一个。为什么当我使用CASE时,我无法使用从ORDER BY中定义的SELECT中的列别名?为什么我不能使用CASE在ORDER BY中引用列别名?

考虑一个简单的查询:

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 NewValueCASE WHEN... that'注释掉了)

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

更新作为的Mikael埃里克森评论用别名在组合的任何表达是不允许的。所以即使这个(没有意义的查询)出于同样的原因失败:

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

结果:

Invalid column name 'Empty'.

所以别名被允许在ORDER BY也是一种表达,但不能同时。为什么,这难以执行?因为我主要是程序员,所以我把别名看作可以简单地用在表达式中的变量。

+0

在此语句排序由“测试”。“COL_1”你为什么不换行外的情况下,条件通过施加磁场和秩序? – 2014-09-10 11:17:09

+1

@AndyKorneyev:我也知道解决方法,但我想知道为什么这是不允许的。这似乎是相当普遍的,一个别名应该隐藏复杂性,所以为什么我不允许这样做,如果我通常可以在'ORDER BY'中使用别名? – 2014-09-10 11:18:18

+0

这里有一个很长的讨论(可能有点过时):http://social.msdn.microsoft.com/Forums/sqlserver/en-US/4ad14cad-1e61-43a0-96f8-70a506106a00/column-alias-usage --everywhere-in-a-query-following-definition?forum = transactsql – davek 2014-09-10 11:23:20

回答

5

这与一个SQL数据库管理系统是如何解析模糊名称做。

我还没有跟踪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。他们陈述的理由是减少含糊不清。

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的

select col_1 as col_2 
from test 
order by col_1; 
+0

谢谢(+)。但问题依然存在:为什么如此?为什么我可以在order_by和别名中使用表达式,但不能同时使用这两个表达式? dbms可以检查是否有别名'NewValue',如果是这样的话,否则就拿一个可用的列名。顺便说一句,'(col_2 +'')的命令;'因为它的工作原因而真的很奇怪。它使用列col_2而不是别名。 – 2014-09-10 14:26:20

+0

我不知道这是为什么。我期望在SQL标准中找到一些东西,但即使在最好的情况下,这也需要我一段时间。 – 2014-09-10 14:37:06

+0

回复:SQL Server 2008中的文档错误 - 也许他们只是没有把正确的重点,可能他们打算说,如果一个别名被用来排序结果集,它应该只是别名(而不是一个表达式使用别名)。坦率地说,非常狂野的猜测。 – 2014-09-10 15:43:18

-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 
+0

谢谢。但正如我所提到的,我知道像sub-queries或CTE这样的解决方法来公开这个列并在任何我喜欢的地方使用它(甚至在'WHERE'中)。但问题是为什么我必须添加复杂性(这是一个子查询肯定)做一些[ORDER BY'应该允许的事情](http://msdn.microsoft.com/en-us/library /ms188385.aspx)(_"**order_by_expression**: 指定对查询结果集进行排序的列或表达式。排序列可以指定为名称**或列别名**,或非负整数表示列表在选择列表“_”中的列的位置。 – 2014-09-10 12:20:15

相关问题