[英]DB2 Sql how to use the case statement?
我正在尝试提取在2个工作日内到期的事件的所有事件结束日期。 因此,对于星期五和星期四,我希望日期在4天或更短的时间内结束,对于星期六的日期希望在3天之内结束,对于在两天之内结束的周三日期,对于在dateval列中列出的所有公共假期,我希望+3 。
下面的脚本不起作用,它仅将日期保留+2天。 我了解我需要使用案例声明,但实际上我不了解如何实现该声明。 有人有什么想法吗?
select event_end_date
from mdmins.table
/*separating by date to find expiring dates*/
where ( (dayofweek(c.event_end_date) in (5,6) /*Friday & Thursday*/
and date(c.event_end_date) < current_date + 4 days
and date(c.event_end_date) >= current_date)
or (dayofweek(c.event_end_date) in (1,2,3,4) /*All other days of week*/
and date(c.event_end_date) < current_date + 2 days
and date(c.event_end_date) >= current_date)
or (dayofweek(c.event_end_date) = 7 /*Saturday - not that this should be needed, but just in case*/
and date(c.event_end_date) < current_date + 3 days
and date(c.event_end_date) >= current_date)
or (date(c.event_end_date) < (select dateval from mdmins.tempdate where dateval = (current date + 3 days)) /*a holiday is on in 3 days, so 2 working days before*/
and date(c.event_end_date) >= current_date) )
从逻辑上讲,一周数据之间唯一不同的是您的预期范围,因此将逻辑限制为使用案例:
...
where date(c.event_end_date) between current_date and current_date +
case
when dayofweek(c.event_end_date) in (5, 6) then 4
when dayofweek(c.event_end_date) in (1, 2, 3, 4) then 2
else 3
end days
or (date(c.event_end_date) < (select dateval
from mdmins.tempdate
where dateval = (current date + 3 days))
and date(c.event_end_date) >= current_date)
where ((date(c.event_end_date) between current_date and current_date +
case
when dayofweek(current date) in (5,6) then 4
when dayofweek(current date) in (1, 2, 3, 4) then 2
else 3
end days)
or date(c.event_end_date) < (select dateval
from mdmins.tempdate
where dateval = (current date + 3 days))
and date(c.event_end_date) >= current_date )
这是一个经典示例,说明了为什么要使用包含所有日期的日历以及大量附加信息。 您将可以执行以下操作:
WITH Desired_Dates AS (SELECT MIN(calendarDate) AS startRange,
MAX(calendarDate) + 1 DAY AS endRange
FROM(SELECT calendarDate
FROM Calendar
WHERE calendarDate >= CURRENT_DATE
AND dayOfWeekISO IN (1, 2, 3, 4, 5)
AND isHolday = '0'
ORDER BY calendarDate
FETCH FIRST 3 ROWS ONLY) D)
SELECT C.<column_list
FROM <Your_Table> C
JOIN Desired_Dates D
ON C.event_end_date >= D.startRange
AND C.event_end_Date < D.endRange
(请注意,我专门使用ISO星期几,其中星期一为1。星期日是1,在美国是星期天,从给定日期导出星期几的功能受当前的异想天开文化设置。此外,在event_end_date
类似于时间戳的情况下,您希望使用专有的结束范围
实际上,这有很大的机会使用仅索引的信息来获取所需的日期(假设有相关的索引),并且在任何情况下都只会在CTE中获取一次数据。
如果您没有日历表,则可以创建一个:
WITH Working_Dates AS (SELECT CURRENT_DATE - 1 DAY AS calendarDate,
0 AS workingDayNum, '0' AS isWorkingDay
FROM SYSIBM/SYSDUMMY1
UNION ALL
SELECT calendarDate,
workingDayNum + CASE WHEN isWorkingDay = 1
THEN 1
ELSE 0 END AS workingDayNum,
isWorkingDay
FROM (SELECT calendarDate, workingDayNum,
CASE WHEN DAYOFWEEK_ISO(WD.calendarDate) IN (6, 7)
OR Holiday.dateval IS NOT NULL
THEN '0'
ELSE '1' END AS isWorkingDay
FROM (SELECT calendarDate + 1 DAY, workingDayNum
FROM Working_Dates
WHERE workingDayNum < 2) WD
LEFT JOIN mdmins.tempdate Holiday
ON Holiday.dateval = WD.calendarDate) WD),
Desired_Dates AS (SELECT MIN(calendarDate) AS startRange,
MAX(calendarDate) + 1 DAY AS endRange
FROM Working_Date
WHERE isWorkingDay = '1')
SELECT C.<column_list
FROM <Your_Table> C
JOIN Desired_Dates D
ON C.event_end_date >= D.startRange
AND C.event_end_Date < D.endRange
这是使用递归CTE循环从当前日期(一个日期之前)到经过三个工作日之间的几天。 (我必须提前一天开始,所以我只需要编写一次“这是一个工作日”逻辑,这也是所有嵌套的原因)。
请注意,您的原始尝试或任何现有的答案都不会考虑这些因素:
通过建立实际工作日列表,我们可以使自己与问题隔离。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.