除了公共假期之外,从当前日期到第5个上一个日期到SQL

时间:2018-01-10 09:40:30

标签: sql sql-server

我需要一个sql函数,除星期六星期日和公众假期外,必须返回第5个上一个营业日期,

例如:我应该在星期四(04-01-2018)获得,如果我之间没有任何公共假期可以实现,

SELECT  DATEADD(DAY, CASE DATENAME(WEEKDAY, GETDATE()) 
                        WHEN 'Sunday' THEN -2 
                        WHEN 'Monday' THEN -3 
                        ELSE -1 END, DATEDIFF(DAY, 5, GETDATE()))

但如何省略公众假期, 任何人都可以帮助我

3 个答案:

答案 0 :(得分:2)

如果你不想(或者你不能)创建一个日历" tally" table(包含标识假日和周末日的列)您可以尝试查询,如下一个。

假期表的样本数据

CREATE TABLE HOL_TAB (DAT DATETIME);
INSERT INTO HOL_TAB VALUES ('2018-01-05');
INSERT INTO HOL_TAB VALUES ('2018-01-04');

查询使用CTE来"创建"在飞行中一个小的计数日历表(我使用12作为限制,但你可以改变它。)

最后SELECT使用带假日表的联接来排除那些日子,然后ROW_NUMBER()提取"首先"五天。

要保持查询类似于我使用的DATENAME,但我建议避免使用它,而是使用其他方法。

WITH CAL_TAB AS (
    SELECT DATEADD(dd, 0, CAST(GETDATE() AS DATE) ) AS DAT
         , 1 AS COUN
    UNION ALL
    SELECT DATEADD(dd, -1- CASE DATENAME (WEEKDAY, DATEADD(dd,-1,B.DAT) ) WHEN 'Sunday' THEN 2 WHEN 'Saturday' THEN 1 ELSE 0 END, B.DAT ) AS DAT
         , B.COUN+1 AS COUN
    FROM CAL_TAB B 
    WHERE B.COUN<12 /* 12 is just to limit number of days */
 )
SELECT DAT, WD
FROM (SELECT C.DAT, C.COUN, DATENAME(WEEKDAY, C.DAT) AS WD, ROW_NUMBER() OVER (ORDER BY COUN) AS RN
      FROM CAL_TAB C
      WHERE NOT EXISTS(SELECT DAT FROM HOL_TAB D WHERE D.DAT=C.DAT)
      ) E WHERE RN<=5;

输出:

    DAT                 WD
1   10.01.2018 00:00:00 Wednesday
2   09.01.2018 00:00:00 Tuesday
3   08.01.2018 00:00:00 Monday
4   03.01.2018 00:00:00 Wednesday
5   02.01.2018 00:00:00 Tuesday

答案 1 :(得分:0)

尝试此逻辑

WITH CTE
AS
(
    SELECT
        MyDate = DATEADD(DD,-5,GETDATE())
)
SELECT
    MyDate = CASE WHEN DATENAME(WEEKDAY, MyDate) IN ('Sunday','Saturday')
                THEN NULL
        WHEN MHL.Holiday IS NOT NULL    
                THEN NULL
        ELSE CTE.MyDate END
    FROM CTE
        LEFT JOIN MyHoliDayList MHL
            ON CTE.MyDate = MHL.Holiday

答案 2 :(得分:0)

尝试此方法:

DECLARE @Holiday TABLE(HoliDay DATE)
INSERT INTO @Holiday VALUES ('2018-01-02')
INSERT INTO @Holiday VALUES ('2018-01-05')

DECLARE @WithOutHoliDay DATETIME = (SELECT DATEADD(DAY, CASE DATENAME(WEEKDAY, GETDATE()) 
                                    WHEN 'Sunday' THEN -2 
                                    WHEN 'Monday' THEN -3
                                    ELSE -1 END, DATEDIFF(DAY, 5, GETDATE())))

SELECT DATEADD(DAY,0-
    (SELECT COUNT(1) 
    FROM @Holiday 
    WHERE HoliDay BETWEEN @WithOutHoliDay AND GETDATE()),@WithOutHoliDay)

这应该给出,你究竟需要什么...