SQL条件连接或where语句

时间:2014-06-27 01:17:21

标签: sql sql-server

我有以下SQL查询

UPDATE ea
    SET ea.isholiday = 1
    FROM employee_attendance ea
    JOIN setup_holiday h ON h.day = DATEPART(dd,ea.timestamp) 
    AND h.month = DATEPART(mm,ea.timestamp)
WHERE ea.isactive = 1

我需要添加其他过滤器:

AND h.year = DATEPART(yyyy, ea.timestamp)

但是,这并不容易,因为如果year = 0

我不想应用此过滤器

有任何线索吗?

3 个答案:

答案 0 :(得分:1)

只需使用or添加条件:

UPDATE ea
    SET ea.isholiday = 1
    FROM employee_attendance ea JOIN
         setup_holiday h
         ON h.day = DATEPART(dd,ea.timestamp) AND
            h.month = DATEPART(mm,ea.timestamp) AND
            (h.year = DATEPART(yyyy, ea.timestamp) or h.year = 0)
WHERE ea.isactive = 1

答案 1 :(得分:0)

你使用一个case语句和一个技巧 - 当你有一个你想要忽略的谓词时,你只需要放右手边(这将永远是真的),否则你的谓词。像这样:

UPDATE ea
    SET ea.isholiday = 1
FROM employee_attendance ea
JOIN setup_holiday h ON h.day = DATEPART(dd,ea.timestamp) 
  AND h.month = DATEPART(mm,ea.timestamp)
WHERE ea.isactive = 1
  AND (CASE WHEN h.year = 0 THEN DATEPART(yyyy, ea.timestamp)
            ELSE h.year END) = DATEPART(yyyy, ea.timestamp)

答案 2 :(得分:0)

对于SQL Server 2005及更高版本:

UPDATE ea
SET
   ea.isholiday = 1
FROM
   dbo.setup_holiday h
   CROSS APPLY (
      SELECT 0, 9999 WHERE h.year = 0
      UNION ALL SELECT h.year, h.year WHERE h.year <> 0
   ) Y (StartYear, EndYear)
   INNER JOIN dbo.employee_attendance ea
      ON h.day = DATEPART(dd, ea.timestamp) 
      AND h.month = DATEPART(mm, ea.timestamp)
      AND h.year BETWEEN Y.StartYear AND Y.EndYear
WHERE
   ea.isactive = 1
;

注意:

  • 请在表格和视图上使用架构前缀(例如dbo.)。这可以防止引擎在当前用户不是数据库管理员时尝试在多个模式中查找对象。我认为不这样做也可能会阻止在您的视图,函数和存储过程中使用WITH SCHEMABINDING,但我现在还不确定。
  • 我更喜欢这种表类型拆分逻辑,而不是复杂的CASE和其他表达式。对我而言,意图更清晰,并且更容易推断结果。一旦了解了CROSS APPLY的工作原理,我认为使用它可以使事情变得更加优雅。
  • 在任何情况下,将h.year子句放在ON子句中比在WHERE子句中更好,因为它是连接的条件,并不是真正的过滤。
  • 如果您是从头开始设计此系统,我建议将StartYearEndYear列放在setup_holiday表中,而不是year,只是这样您可以在没有CROSS APPLY的情况下遵循此确切模式。这也允许你停止使用0年度的“魔术值”(有时称为“哨兵值”) - 它只是起作用,并支持年份范围,此外 - 当前系统的脆弱性只支持指定每年或根本不支持年份。
  • 最佳做法是使用分号;结束查询,以便在将来验证代码并消除CTE之前使用分号的愚蠢行为。 Although the semicolon is not required for most statements in SQL Server 2014 and earlier, it will be required in a future version
  • 虽然这完全取决于个人偏好,但是如果将相同缩进级别的项目置于不同的重要位置(将FROMJOIN和{{1}排列在一起),您怎么可能有效地阅读查询?哪些都有不同的意义)?你怎么能容忍在AND行的末尾有一些ON条件,有些在下一行?在我看来,你通过选择一种不能正确利用缩进并将相同的东西放在一起的格式,在行的开头处有重要的信号词,就会损害你的最终查询扫描速度。