选择查询 - 从日期范围获取的总日计数中排除假日计数

时间:2013-08-12 10:41:51

标签: sql-server sql-server-2008

我有一个项目表,其字段为name,startdate,enddate, 使用datediff我计算了总日数,然后将星期日过滤为colname TotalDay_sundayremoved

我有另一张表作为假期,现在必须在TotalDay_sundayremoved列上过滤这些假期

DDL:

CREATE TABLE holiday_hd (
      date_hd DATETIME
    , enent_hd VARCHAR(200)
);
INSERT INTO holiday_hd
VALUES 
    ('2013-03-15 00:00:00.000', 'Aniversry Leave'),
    ('2013-08-15 00:00:00.000', 'Independence Day'),
    ('2014-08-15 00:00:00.000', 'Independence Day');

CREATE TABLE Project_pj (
      Name VARCHAR(200)
    , start_date_pj DATETIME
    , ed_date_pj DATETIME
    , expectedend_date_pj DATETIME
);
INSERT INTO Project_pj
VALUES 
    ('aaa', '2012-12-01 00:00:00.000', '2023-07-22 00:00:00.000', NULL),
    ('bbb', '2012-12-01 00:00:00.000', NULL, '2023-07-22 00:00:00.000'),
    ('ccc', '2013-12-01 00:00:00.000', NULL, '2014-07-22 00:00:00.000'),
    ('ddd', '2013-07-01 00:00:00.000', NULL, '2016-07-22 00:00:00.000');

查询:

SELECT
      Name
    , start_date_pj
    , ISNULL(ed_date_pj, expectedend_date_pj) AS enddate
    , DATEDIFF(DAY, start_date_pj, ISNULL(ed_date_pj, expectedend_date_pj)) AS No_Days
    , (DATEDIFF(dd, start_date_pj, ISNULL(ed_date_pj, expectedend_date_pj)) + 1)
      - (DATEDIFF(wk, start_date_pj, ISNULL(ed_date_pj, expectedend_date_pj)) * 1)
      - (CASE WHEN DATENAME(dw, start_date_pj) = 'Sunday' THEN 1 ELSE 0 END) AS TotalDay_sundayremoved
FROM Project_pj

SQL FIDDLE DEMO

1 个答案:

答案 0 :(得分:2)

试试这个 -

SELECT
      name
    , start_date_pj
    , enddate
    , No_Days = DATEDIFF(DAY, start_date_pj, enddate) 
    , TotalDay_sundayremoved = (DATEDIFF(dd, start_date_pj, enddate) + 1)
         - (DATEDIFF(wk, start_date_pj, enddate) * 1)
         - (CASE WHEN DATENAME(dw, start_date_pj) = 'Sunday' THEN 1 ELSE 0 END) 
        -- - holidays
    , holidays
FROM (
    SELECT 
          name
        , start_date_pj
        , enddate = ISNULL(ed_date_pj, expectedend_date_pj)
    FROM dbo.Project_pj
) p
OUTER APPLY (
    SELECT holidays = COUNT(1)
    FROM dbo.holiday_hd h
    WHERE h.date_hd BETWEEN p.start_date_pj AND p.enddate
) t

您也可以编写子查询 -

SELECT
      name
    , ...
    , holidays = (
        SELECT holidays = COUNT(1)
        FROM dbo.holiday_hd h
        WHERE h.date_hd BETWEEN p.start_date_pj AND p.enddate
      )
FROM (
    SELECT 
          name
        , start_date_pj
        , enddate = ISNULL(ed_date_pj, expectedend_date_pj)
    FROM dbo.Project_pj
) p

<强>更新

SELECT
      name
    , start_date_pj
    , enddate
    , No_Days = DATEDIFF(DAY, start_date_pj, enddate) 
    , TotalDay_sundayremoved = (DATEDIFF(dd, start_date_pj, enddate) + 1)
         - (DATEDIFF(wk, start_date_pj, enddate) * 1)
         - isSunday
        -- - holidays
    , TotalDay_holidayRmoved = (DATEDIFF(dd, start_date_pj, enddate) + 1)
         - (DATEDIFF(wk, start_date_pj, enddate) * 1)
         - isSunday
         - t.holidays
    , t.holidays
    , currentDays_removeSunday = (DATEDIFF(dd, start_date_pj, GETDATE()) + 1)
                 - (DATEDIFF(wk, start_date_pj, GETDATE()) * 1)
                 - isSunday
    , holidays_currentDateCount= holidays_now

    , Currentday_Removeholiday_RemoveSundays_tilldate= DATEDIFF(dd, start_date_pj,  GETDATE()+1) 
                        -(DATEDIFF(wk, start_date_pj, GETDATE()) * 1)
                        - isSunday
                        - holidays_now
FROM (
    SELECT 
          name
        , start_date_pj
        , enddate = ISNULL(ed_date_pj, expectedend_date_pj)
        , isSunday = CASE WHEN DATENAME(dw, start_date_pj) = 'Sunday' THEN 1 ELSE 0 END
    FROM dbo.Project_pj
) p
OUTER APPLY (
    SELECT 
          holidays = SUM(holidays) 
        , holidays_now = SUM(holidays_now)
    FROM (
        SELECT 
              holidays = CASE WHEN h.date_hd BETWEEN p.start_date_pj AND p.enddate THEN 1 ELSE 0 END
            , holidays_now = CASE WHEN h.date_hd BETWEEN p.start_date_pj AND GETDATE() THEN 1 ELSE 0 END
        FROM dbo.holiday_hd h
    ) t
) t