SQL Server中的天差

时间:2015-12-21 16:35:28

标签: sql-server sql-server-2008

我对SQL Server有疑问。

表:holidaylist

Date       |  weekendStatus   | Holidaystatus
2015-12-01 |   0              | 0
2015-12-02 |   0              | 0
2015-12-03 |   0              | 0
2015-12-04 |   1              | 0
2015-12-05 |   1              | 0
2015-12-06 |   0              | 1
2015-12-07 |   0              | 0
2015-12-08 |   0              | 0
2015-12-09 |   0              | 1
2015-12-10 |   0              | 0
2015-12-11 |   0              | 0
2015-12-12 |   1              | 1
2015-12-13 |   1              | 0

表:emp

empid  |  doj       | dos
1      | 2015-12-01 | 2015-12-06
2      |2015-12-01  | 2015-12-13
3      |2015-12-03  |2015-12-13

我希望与dos-doj没有weekenstatusandholidaysstatus有天差 并包括周末和度假状态

我想要这样的输出:

Empid    |   doj         | dos       |includeweekendandholidays  |  witoutincludeweekendandholidayslist
1        |  2015-12-01   |2015-12-06 |    5                      |   3    
2        | 2015-12-01    |2015-12-13 |    12                     |   8
3        | 2015-12-03    |2015-12-13 |    10                     |   6

我尝试了这个查询:

select 
    a.empid, a.doj, a.dos, 
    case 
        when b.weekendstatus = 1 and c.Holidaystatus = 1  
           then datediff(day, c.date, b.date) 
    end as includeweekenandholidays
    case 
        when b.weekendstatus != 1 or c.Holidaystatus = 1  
           then datediff(day, c.date, b.date) 
    end as witoutincludeweekendandholidayslist
from 
    emp a 
left join 
    holidaylist b on a.doj = b.date
left join  
    holidaylist c on a.dos = c.date

以上查询未给出预期结果请告诉我如何编写查询以在SQL Server中实现此任务

4 个答案:

答案 0 :(得分:1)

试试这个:

select a.empid,
       a.doj,a.dos, 
       IncludeRest = (select count(h.date) from holidaylist h where e.doj<=h.date AND e.dos>=h.date),
       ExcludeRest = (select count(h.date) from holidaylist h where e.doj<=h.date AND e.dos>=h.date AND h.weekendstatus = 0 AND h.holdaystatus = 0)
from emp e

答案 1 :(得分:0)

您可以使用OUTER APPLY

SELECT a.empid, a.doj, a.dos, 
       DATEDIFF(d, a.doj, a.dos) + 1 AS include,
       DATEDIFF(d, a.doj, a.dos) + 1 - b.wd - b.hd + b.common AS without
FROM emp AS a
OUTER APPLY (
  SELECT SUM(weekendStatus) AS wd, 
         SUM(Holidaystatus) AS hd,
         COUNT(CASE WHEN weekendStatus = 1 AND Holidaystatus = 1 THEN 1 END) AS common
  FROM holidaylist
  WHERE [Date] BETWEEN a.doj AND a.dos) AS b

对于表emp的每一行,OUTER APPLY计算与此行间隔对应的weekendStatus=1Holidaystatus=1行。

选择的计算字段:

  • 包含emp间隔的总天数,包括周末日和假日。
  • emp间隔减去周末天和假日的总天数。 常用字段可确保常规周末和假日不会减去两次

注意:以上查询包括计算中间隔的开始和结束日期,因此考虑的间隔为[doj-dos]。您可以更改WHERE操作中OUTER APPLY子句的谓词,以便排除时间间隔的开始,结束或两者。

Demo here

答案 2 :(得分:0)

您可以在COUNT中使用CASE来确定是否计算当天..

SELECT
    e.empid,
    e.doj,
    e.dos,
    COUNT(*) includeweekendandholidays,
    COUNT(CASE WHEN Holidaystatus = 0
                    AND [weekendStatus] = 0 THEN 1
          END) withoutincludeweekendandholidayslist
FROM
    emp e
    JOIN holidaylist hl ON hl.Date >= e.doj
                           AND hl.Date < e.dos
GROUP BY
    e.empid,
    e.doj,
    e.dos

这可能会表现得更好,因为它只会加入到您需要的记录上的holidaylist表中。

SELECT
    e.empid,
    e.doj,
    e.dos,
    DATEDIFF(DAY, e.doj, e.dos) includeweekendandholidays,
    COUNT(*) withoutincludeweekendandholidayslist
FROM
    emp e
    JOIN holidaylist hl ON hl.Date BETWEEN e.doj AND e.dos
WHERE 
    weekendStatus = 0 
    AND Holidaystatus = 0
GROUP BY
    e.empid,
    e.doj,
    e.dos,
    DATEDIFF(DAY, e.doj, e.dos)

我没有得到你的输出,因为它只是看起来你不排除周末而不是假期..

答案 3 :(得分:0)

尝试使用交叉连接的另一种方式

select t.empid,t.doj,t.dos,datediff(day,t.doj,t.dos) includeweekendandholidays,
datediff(day,t.doj,t.dos)-isnull(t1.wes,0) as witoutincludeweekendandholidayslist 
from @emp t  left join (

select empid, sum(hd.Holidaystatus+hd.weekendStatus) wes from 
@emp emp cross join @holidaylist hd where hd.[Date]  between doj 
and dateadd(day,-1,dos) group by empid) t1 on t.empid=t1.empid

示例数据

 declare @holidaylist table ([Date] date,  weekendStatus int, Holidaystatus int)
insert into @holidaylist([Date],  weekendStatus, Holidaystatus) values
('2015-12-01' ,   0              , 0),
('2015-12-02' ,   0              , 0),
('2015-12-03' ,   0              , 0),
('2015-12-04' ,   1              , 0),
('2015-12-05' ,   1              , 0),
('2015-12-06' ,   0              , 1),
('2015-12-07' ,   0              , 0),
('2015-12-08' ,   0              , 0),
('2015-12-09' ,   0              , 1),
('2015-12-10' ,   0              , 0),
('2015-12-11' ,   0              , 0),
('2015-12-12' ,   1              , 1),
('2015-12-13' ,   1              , 0)

declare @emp table(empid  int,  doj  date,     dos date)
insert into @emp (empid,doj,dos) values
(1      , '2015-12-01' , '2015-12-06'),
(2      ,'2015-12-01'  , '2015-12-13'),
(3      ,'2015-12-03'  ,'2015-12-13')