如何在WHERE中重用CASE?

时间:2011-01-05 08:30:03

标签: sql sql-server

我正在尝试执行看起来像这样的请求

SELECT field1, field2, field3 = CASE
    WHEN field2 = 'something' THEN 'something'
    WHEN field1 IS NOT NULL and field2 IS NULL THEN 'somethingElse'
    ELSE NULL
    END
FROM SomeTable
WHERE field3 IS NOT NULL

这会导致语法错误。我必须在WHERE中重写CASE而不是仅仅引用它。有没有更好的方法来实现这一目标?

出于好奇,为什么“WHERE field3 IS NOT NULL”被拒绝,例如“ORDER BY field3”会通过?

3 个答案:

答案 0 :(得分:3)

SELECT * 
FROM (
  SELECT field1, 
         field2, 
         CASE
            WHEN field2 = 'something' THEN 'something'
            WHEN field1 IS NOT NULL and field2 IS NULL THEN 'somethingElse'
           ELSE NULL
         END as field3
  FROM your_table
) T
WHERE field3 IS NOT NULL

答案 1 :(得分:1)

这种方法的问题在于它使谓词不可思议。这意味着可以通过一些索引搜索满足的查询最终使用扫描。

设置测试表

create table SomeTable
(
id int identity(1,1) primary key nonclustered,
field1 varchar(20),
field2 varchar(20)
)

create clustered index ix on SomeTable(field2, field1)

INSERT INTO SomeTable
SELECT left(name,20),left(name,20)
FROM sys.all_columns
UNION ALL
SELECT 'foo','something'
UNION ALL
SELECT 'bar',NULL

没有CASE的谓词

SELECT field1, field2, field3 = CASE
    WHEN field2 = 'something' THEN 'something'
    WHEN field1 IS NOT NULL and field2 IS NULL THEN 'somethingElse'
    END
FROM SomeTable
WHERE field2 = 'something' OR (field2 IS NULL AND field1 IS NOT NULL)

带CASE的谓词

SELECT * 
FROM (
  SELECT field1, 
         field2, 
         CASE
            WHEN field2 = 'something' THEN 'something'
            WHEN field1 IS NOT NULL and field2 IS NULL THEN 'somethingElse'
           ELSE NULL
         END as field3
  FROM SomeTable
) derived
WHERE field3 IS NOT NULL

执行计划

Plan

答案 2 :(得分:0)

SELECT field1, field2, CASE
    WHEN field2 = 'something' THEN 'something'
    WHEN field1 IS NOT NULL and field2 IS NULL THEN 'somethingElse'
    ELSE NULL
    END
FROM SomeTable
WHERE CASE
    WHEN field2 = 'something' THEN 'something'
    WHEN field1 IS NOT NULL and field2 IS NULL THEN 'somethingElse'
    ELSE NULL
    END IS NOT NULL