DB2 Sql如何使用case语句?

时间:2014-09-18 10:05:07

标签: sql db2 case-statement

我正在尝试提取在2个工作日内到期的活动的所有活动结束日期。因此,对于星期五和星期四,我希望​​日期在4天或更短时间内结束,星期六日期在3天内结束,太阳星期三日期在2天内结束,+ 3表示所有公共假日,列在日期列中的tempdate

以下脚本不起作用,只接受+2天的日期。我理解我需要使用case语句,但我真的不明白如何实现它。有人有什么想法吗?

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) ) 

3 个答案:

答案 0 :(得分:0)

从逻辑上讲,本周数据之间唯一不同的是你看多远,所以使用案例限制逻辑:

...
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)

答案 1 :(得分:0)

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 )

答案 2 :(得分:0)

这是一个典型的例子,说明为什么你想要一个包含所有日期的日历,以及一堆额外的信息。你能够做类似的事情:

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循环从当前日期(一个之前)到三个工作日过去的天数。 (我必须提前一天开始,所以我只需要写#34;它是一个工作日&#34;逻辑一次,这也是所有嵌套的原因。)

请注意,您的原始尝试或任何现有答案都不考虑这些:

  1. 如果周五或周一有假期(5天跳过,而不是4天)会怎样?
  2. 如果按顺序有多个假期(跳过未知天数)会怎样?
  3. 通过建立实际工作日的清单,我们可以将自己与问题隔离开来。