在 where 子句中使用 case 语句

using case statement in a where clause

您好,由于我的代码错误,我遗漏了一些东西。

select * from ##ScheduleDetail SD
left join ##HolidayFilterTbl HF on SD.Scheduledate = HF.Testdate

where (ScheduleDate = testdate)
and
(Case 
 when HF.IsHoliday = 1 then (overtime = 1 and makeup = 0)
 else
(overtime = 0 and Makeup = 0)
end
)
and
DOW = 5 
order by ActivityStartTime

我尝试了多种组合,但每一种组合都在第一个等号或第二个等号处出错。我错过了什么?

case 表达式的分支只能 return 值,不能在 where 条件下计算其他表达式。但是,您可以使用 andor 逻辑运算符模拟此行为:

select    *
from      ##ScheduleDetail SD
left join ##HolidayFilterTbl HF on SD.Scheduledate = HF.Testdate
where     (ScheduleDate = testdate) and
          ((HF.IsHoliday = 1 and overtime = 1 and makeup = 0) or
           (overtime = 0 and Makeup = 0)) and
          DOW = 5 
order by  ActivityStartTime

请注意,问题中 case 表达式的两个分支(或答案中 or 的两侧)都有 makeup = 0,因此您可以将其提取出来它并稍微简化条件:

select    *
from      ##ScheduleDetail SD
left join ##HolidayFilterTbl HF on SD.Scheduledate = HF.Testdate
where     ScheduleDate = testdate and
          makeup = 0 and
          ((HF.IsHoliday = 1 and overtime = 1) or
           overtime = 0) and
          DOW = 5 
order by  ActivityStartTime

如果您仍然想知道如何在 WHERE 子句中使用 CASE 语句 表达式,则必须将 CASE 表达式与一个值进行比较,因为这是对条件理解的语法包含在 WHERE 子句中。请参阅下面的模拟示例。

SELECT *
FROM ##ScheduleDetail SD
     LEFT JOIN ##HolidayFilterTbl HF ON SD.Scheduledate = HF.Testdate
WHERE(ScheduleDate = testdate)
     AND
     /* If you wish to stick with using a CASE Expression within the WHERE Clause set the the CASE Expression equal to 'something'.  I usually stick with 1 or 0 'true/false'.
      |  You simply have to create your own True/False evaluation.  You can add your logic checks within a CASE Expression within
      |  the WHERE Clause and when your logic is TRUE THEN return 1.  Basically you are saying when 1 = 1 then return Record.
     */
     1 = 
     Case 
      WHEN HF.IsHoliday = 1 AND makeup = 0 THEN
        CASE WHEN (overtime = 1 OR overtime = 0) THEN 1 END /* Return 1 here to evaluation to TRUE */
      ELSE      
        0 /* You can add another CASE here if needed and when the condition you write in evaluations to 1 'true' return record */
      END
     
     AND
     DOW = 5

ORDER BY ActivityStartTime;

我在 WHERE 子句中使用 CASE 表达式而不是 AND/ORs 有几个原因。一个次要的原因是它允许我在 CASE 表达式内的 WHERE 子句中包含和组织逻辑,而不是将多个 AND/ORs 全部嵌套在一起。我还发现,在遇到接受变量的动态查询时,在 WHERE 子句中使用 CASE 表达式很有用,这些变量稍后将插入到 SQL 中,然后再发送到数据库进行处理。在使用 Dynamic SQL 的情况下,有时必须使用 CASE 语句,因为在 WHERE 子句中可能存在被比较的数据不是 column.field 值,而是与用户选择或状态(例如)进行比较的硬编码值...它可能是通过应用程序传入的静态值,这就是我支持的 Web 应用程序的工作方式,这就是我提出它的原因。

基本上,了解如何在 WHERE 子句中使用 CASE 表达式是件好事,因为在某些情况下,评估某些数据的唯一方法是使用 CASE 表达式。

我没有数据可以对此进行测试,这不是重点。我的回答的重点是简单地为您提供现有答案的替代方案。在我看来,这个逻辑是基本的,已经提供的答案是正确的,但我的答案是为了演示如何在 WHERE 子句中使用 CASE。

如果有兴趣,请参阅 this SO Post 以了解 CASE 语句与 CASE 表达式之间的区别,但要知道该术语在数据库之间略有不同。

举个例子... SQL 服务器将它们称为 Simple vs Searched 但将它们全部称为 CASE 表达式。因此,CASE 表达式可以是简单的或搜索的 CASE,可以在语句中使用。