我有以下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
有任何线索吗?
答案 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
子句中更好,因为它是连接的条件,并不是真正的过滤。 StartYear
和EndYear
列放在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。FROM
与JOIN
和{{1}排列在一起),您怎么可能有效地阅读查询?哪些都有不同的意义)?你怎么能容忍在AND
行的末尾有一些ON
条件,有些在下一行?在我看来,你通过选择一种不能正确利用缩进并将相同的东西放在一起的格式,在行的开头处有重要的信号词,就会损害你的最终查询扫描速度。