【问题标题】:Adjusting date if date falls on a weekend or bank holiday如果日期是周末或银行假日,则调整日期
【发布时间】:2018-05-08 18:19:10
【问题描述】:

我有一个查询,它从临时表 myTblTemp 向表 myTbl 中插入一些新记录。

如果日期是星期六或星期日,我会在查询中调整“AnnDate”字段之一。但是,如果日期是银行假日,我还需要调整 AnnDate。

我有一张表 tblBankHoliday,其中列出了所有需要的即将到来的银行假期。如果在 tblBankHoliday 中找到了 AnnDate,我该如何调整我的查询(或者我是否需要一个单独的查询)以增加一天的日期?

我当前的查询

insert into myTbl(AnnDate, USDVal)
case DATENAME(WEEKDAY, AnnDate) 
       when 'Saturday' 
       then DATEADD(DD, 2, AnnDate) 
       when 'Sunday' 
       then DATEADD(DD, 1, AnnDate) 
       else AnnDate 
end
from myTblTemp

【问题讨论】:

  • tblBankHoliday 相比,您是否考虑过使用一个包含所有日期的日历表来列出所有 个日期。然后,您通常会得到(从其他列计算或直接存储)一个“是工作日”样式的列,您可以从该列中以 uniform 方式解决此问题,而不是尝试处理周末和银行假期分别。
  • 这可能是一个好的开始:Bones of SQL - The Calendar Table

标签: sql sql-server


【解决方案1】:

制作一张桌子,例如thedays。将相关期间的所有日期插入其中。例如在theday 列中。在另一列中,例如isworkday 将工作日标记为 1,非工作日标记为 0。

然后您可以在查询中选择给定日期或之后的下一个工作日。

insert into myTbl(AnnDate, USDVal)
(SELECT min(theday)
        FROM thedays
        WHERE theday >= AnnDate
              AND theday.isworkday = 1)
...
from myTblTemp

【讨论】:

    【解决方案2】:

    Sticky bit 的答案更适合您的情况。


    您可以使用递归 CTE 在无效日期之间循环,并不断增加 1 天,直到您的验证完成。

    ;WITH PatchedDates AS
    (
        SELECT
            InitialAnnDate = C.AnnDate,
            CorrectedAnnDate = C.AnnDate,
            USDVal = C.USDVal,
            IsDateOK = CASE 
                WHEN 
                    EXISTS (SELECT 1 FROM tblBankHoliday AS X WHERE X.BankHoliday = C.AnnDate) OR 
                    DATENAME(WEEKDAY, C.AnnDate) IN ('Saturday', 'Sunday') THEN 'No' 
                ELSE 'Yes' END
        from 
            myTblTemp AS C
            LEFT JOIN tblBankHoliday AS T ON C.AnnDate = T.BankHoliday
    
        UNION ALL
    
        SELECT
            InitialAnnDate = C.InitialAnnDate,
            CorrectedAnnDate = DATEADD(DAY, 1, C.CorrectedAnnDate),
            USDVal = C.USDVal,
            IsDateOK = CASE 
                WHEN 
                    EXISTS (SELECT 1 FROM tblBankHoliday AS X WHERE X.BankHoliday = DATEADD(DAY, 1, C.CorrectedAnnDate)) OR 
                    DATENAME(WEEKDAY, DATEADD(DAY, 1, C.CorrectedAnnDate)) IN ('Saturday', 'Sunday') THEN 'No' 
                ELSE 'Yes' END
        FROM
            PatchedDates AS C
        WHERE
            C.IsDateOK = 'No'
    )
    insert into myTbl(
        AnnDate, 
        USDVal)
    SELECT
        AnnDate = C.CorrectedAnnDate,
        USDVal = C.USDVal
    FROM
        PatchedDates AS C
    WHERE
        C.IsDateOK = 'Yes'
    

    【讨论】:

      猜你喜欢
      • 2018-02-08
      • 2021-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多