【问题标题】:using case statement in a where clause在 where 子句中使用 case 语句
【发布时间】:2021-03-14 21:14:27
【问题描述】:

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

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 表达式尝试,改用 AND/OR。
  • CASE 表达式必须生成单个值,而不是要计算的附加代码。
  • @JoelCoehoorn, (overtime = 1 and makeup = 0) 返回 TRUE/FALSE/null。
  • 用您正在使用的数据库标记您的问题。

标签: sql select where-clause case-statement


【解决方案1】:

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

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

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

如果有兴趣,请参阅 this SO Post 了解 CASE 语句与 CASE 表达式之间的差异,但是请注意,数据库之间的术语略有不同。

作为一个例子...... SQL Server 将这些称为Simple vs Searched,但将其全部称为 CASE 表达式。因此,CASE 表达式既可以是简单的,也可以是可在语句中使用的搜索过的 CASE。

【讨论】:

  • @jarlh 更新为使用 Expression vs Statement 但是我发现在比较不同的数据库和它们使用的术语时,术语很松散,并不总是一对一。
  • 很多人都不知道。但主要区别在于 case 表达式返回一个值,而 case 语句用于有条件地执行代码(通常在存储过程中)。
【解决方案2】:

case 表达式的分支只能返回值,而不能在 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 表达式的两个分支上都有makeup = 0(或答案中or 的两侧),因此您可以从中提取它并稍微简化条件:

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

【讨论】:

  • case表达式可以返回布尔表达式(overtime = 1 and makeup = 0)的结果,它是一个布尔值。 (仍然是个坏主意。)
猜你喜欢
  • 2018-07-04
  • 1970-01-01
  • 1970-01-01
  • 2013-10-16
  • 2017-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-08
相关资源
最近更新 更多