什么时候评估 CASE 语句?

When is the CASE statement evaluated?

我对 AdventureWorks2012 数据库有以下查询

SELECT  productid,
        productname,
        unitprice,
        CASE
            WHEN unitprice < 20.0 THEN 'LOW'
            WHEN unitprice < 40.0 THEN 'MEDIUM'
            WHEN unitprice >= 40.0 THEN 'HIGH'
        END pricerange
FROM    Production.Products
ORDER BY
    CASE
        WHEN pricerange < 'LOW' THEN 1
        WHEN pricerange < 'MEDIUM' THEN 2
        WHEN pricerange >= 'HIGH' THEN 3
    END ASC
GO

ORDER BY发生在SELECT语句之后,但是pricerange列名无法访问?我假设 SELECT 语句中的价格范围是在调用 ORDER BY 之后计算的?这是为什么?

SQL 是一种声明性语言,而不是命令性语言。执行顺序未定义,而且并不总是相同。

无论如何,执行顺序并不重要。重点是 scope - 并且 pricerange 不在该 select 语句的任何范围内。与其考虑代码行出现的顺序(如命令式编程),不如考虑每个表达式如何包裹另一个表达式。

在这种情况下,您正在做这样的事情:

Select(OrderBy(From(Products), ...), ...)

您有两种解决方法 - 一种选择是使用与您在 select 中使用的顺序相同的大小写(别担心,引擎足够聪明,不会这样做工作两次)。第二种是将您的查询包装在另一个执行实际排序的查询中:

select * from
(
  SELECT  productid,
          productname,
          unitprice,
          CASE
              WHEN unitprice < 20.0 THEN 'LOW'
              WHEN unitprice < 40.0 THEN 'MEDIUM'
              WHEN unitprice >= 40.0 THEN 'HIGH'
          END pricerange
  FROM Production.Products
)
ORDER BY
    CASE
       WHEN pricerange < 'LOW' THEN 1
       WHEN pricerange < 'MEDIUM' THEN 2
       WHEN pricerange >= 'HIGH' THEN 3
    END ASC

但请记住,您在这里处理的是表达式树,而不是命令列表。您是在描述您想要什么,而不是如何执行。 如何 是执行引擎的工作。

最后,执行引擎可能会为查询的两种变体制定相同的执行计划——它们并没有真正的不同;例如,虽然 NULL 周围可能存在一些极端情况,但我不确定。

SQL服务器解释逻辑处理documentation中查询的顺序。

  1. FROM
  2. ON
  3. JOIN
  4. WHERE
  5. GROUP BY
  6. WITH CUBE or WITH ROLLUP
  7. HAVING
  8. SELECT
  9. DISTINCT
  10. ORDER BY
  11. TOP

请注意,这是 合乎逻辑的。实际上,这意味着排序在查询的编译阶段主要用于确定引用的名称。另请注意,该列表是关键字和子句的奇怪组合(ONWITHDISTINCTTOP 不是 SQL 子句)。

至于你的查询,pricerange的定义是由SELECT中的逻辑决定的。然后在 ORDER BY 中进一步使用它来获得您想要的顺序。这是处理的逻辑描述。

实际上,我希望 SQL 服务器在扫描数据时计算 pricerange 和排序优先级(SQL 服务器通过在读取数据)。 pricerange 计算进入最终结果集。订购件仅供 ORDER BY.

使用