CASE WHEN in WHERE 语句

use*_*057 2 sql teradata sql-server-2008

我对 SQL 非常陌生,并且在使用 Where 语句时遇到了问题。我正在尝试查看昨天和一周后的支票,除非今天(今天是查询运行的那一天)是星期一,否则我想查看星期五和星期五之前。错误消息是“期望在‘Check_date’和‘=’之间有一些东西。

WHERE
    CASE WHEN DAYOFWEEK(date) = 2 
        THEN (a.check_date = DATE - 3 OR a.check_date = DATE - 10)
        ELSE (a.check_date = DATE - 1 OR a.check_date = DATE - 8) END
Run Code Online (Sandbox Code Playgroud)

Aar*_*and 5

在 T-SQL 中,CASE是从分支之一返回单个值的表达式。它不是一个语句,不能像在其他语言中那样用于控制流。你不能把整个条件放在里面。语义差异可能看起来很小,但行为差异是显着的。

CASE在这种情况下使用表达式(没有双关语)不会很有价值,因为它需要多个分支,例如(我只是在这里猜测,因为您当前的查询并不是很清楚您要做什么):

WHERE a.checkdate IN 
  (DATEADD(DAY, 0-CASE DATEPART(WEEKDAY, [DATE]) 
    WHEN 2 THEN 3  ELSE 1 END, [DATE]),
  (DATEADD(DAY, 0-CASE DATEPART(WEEKDAY, [DATE]) 
    WHEN 2 THEN 10 ELSE 8 END, [DATE]);
Run Code Online (Sandbox Code Playgroud)

当然,CASE在不无故引入表达式的情况下将它们组合起来要容易得多:

WHERE 
  (
    DATEPART(WEEKDAY, [DATE]) = 2
    AND a.checkdate IN (DATEADD(DAY, -3, [DATE]), DATEADD(DAY, -10, [DATE]))
  )
  OR
  (
    DATEPART(WEEKDAY, [DATE]) <> 2
    AND a.checkdate IN (DATEADD(DAY, -1, [DATE]), DATEADD(DAY, -8,  [DATE]))
  );
Run Code Online (Sandbox Code Playgroud)

更容易的是预先定义两个变量(尽管我不确定 teradata 如何处理批处理):

 DECLARE @d1 DATE, @d2 DATE;

 SET @d1 = DATEADD(DAY, -1, [DATE]);
 SET @d2 = DATEADD(DAY, -8, [DATE]);

 IF DATEPART(WEEKDAY, [DATE]) = 2
 BEGIN
   SELECT @d1 = DATEADD(DAY, 2, @d1), @d2 = DATEADD(DAY, 2, @d2);
 END

 SELECT ...
 WHERE a.checkdate IN (@d1, @d2);
Run Code Online (Sandbox Code Playgroud)