在 ORDER BY 中使用带有别名列的计算

Using calculation with an an aliased column in ORDER BY

众所周知,ORDER BY子句是在SELECT子句之后处理的,所以在SELECT子句中可以使用列别名。

但是,我发现我不能在 ORDER BY 子句的计算中使用别名列。

WITH data AS(
    SELECT *
    FROM (VALUES
        ('apple'),
        ('banana'),
        ('cherry'),
        ('date')
    ) AS x(item)
)
SELECT item AS s
FROM data
--  ORDER BY s;         -- OK
--  ORDER BY item + ''; -- OK
ORDER BY s + '';        -- Fails

我知道有其他方法可以执行此特定查询,而且我知道这是一个微不足道的计算,但我想知道为什么列别名在计算中不起作用。

我已经在 PostgreSQL、MariaDB、SQLite 和 Oracle 中进行了测试,它按预期工作。 SQL服务器似乎是奇数。

这仅仅是因为表达式的计算方式。一个更说明性的例子:

;WITH data AS
(
   SELECT * FROM (VALUES('apple'),('banana')) AS sq(item)
)
SELECT item AS s
  FROM data
  ORDER BY CASE WHEN 1 = 1 THEN s END;

这 returns 相同的 Invalid column name 错误。在解析 select 列表中的别名之前计算 CASE 表达式(以及更简单情况下的 s + '' 的串联)。

一种更简单的解决方法是在 select 列表中附加空字符串:

SELECT
  item + '' AS s
...
ORDER BY s;

还有更复杂的方法,比如使用派生的 table 或 CTE:

;WITH data AS
(
  SELECT * FROM (VALUES('apple'),('banana') AS sq(item)
),
step2 AS
(
  SELECT item AS s FROM data
)
SELECT s FROM step2 ORDER BY s+'';

这就是 SQL 服务器的工作方式,我想你可以说“好吧 SQL 服务器因此很糟糕”,但 SQL 服务器也可以说“这个用例到底是什么?” :-)

documentation 明确指出:

The column names referenced in the ORDER BY clause must correspond to either a column or column alias in the select list or to a column defined in a table specified in the FROM clause without any ambiguities. If the ORDER BY clause references a column alias from the select list, the column alias must be used standalone, and not as a part of some expression in ORDER BY clause:

从技术上讲,您的查询应该有效,因为 order by 子句在 逻辑上 在 select 子句之后计算,并且它应该可以访问 [=25= 中声明的所有表达式] 条款。但是如果 查看 可以访问 SQL 规范,我无法评论它是否是 SQL 服务器或其他 RDBMS 的限制,将其作为奖励功能实现。

无论如何,您可以使用 CROSS APPLY 作为技巧....它是 FROM 子句的一部分,因此表达式应该在所有后续子句中可用:

SELECT item
FROM t
CROSS APPLY (SELECT item + '') AS CA(item_for_sort)
ORDER BY item_for_sort