2015-12-21 73 views
2

我有一个关于SQL Server的问题。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的司法部天差withoutweekenstatusandholidaysstatus 和includeweekendandholidaystatus

我想这样的输出:

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此任务

+2

这是什么意思'withoutweekenstatusandholidaysstatus和includeweekendandholidaystatus'? –

+0

尝试使用[日期] BETWEEN [doj]和[dos]加入您的表格一次。这会在开始日期和结束日期之间每天给你一行。你可以在WHERE子句中过滤掉你不想要的记录。现在你将只有你想要的记录,你可以计算。 –

+0

我们需要天差异b/w dos和doj为每个empid和输出需要包括wekenken和holidayststatusdays意味着多少天与wekenstatusandholidays一起工作,没有weenkenstatusandholidaysstatus意味着需要找到他工作了多少天,没有节假日和周末天和周末天找到holidayslist和weekendlist查看holidayslist table.please告诉我如何编写查询以在sql server中完成此任务 – ravi

回答

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]。您可以更改OUTER APPLY操作中的WHERE子句的谓词,以排除间隔的开始日期,结束日期或两者的天数。

Demo here

+0

嗨,您可以在不使用外部应用查询的情况下提供该函数吗?当我在update语句中使用相同的逻辑时时间outerapply需要更多的时间和它的查杀性能also.for逻辑明智给查询工作fine.I需要备用查询请提供它 – ravi

+0

@ravi我会建议尝试杰米的答案。 –

0

您可以使用您帐户中的一个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) 

我没有得到你的输出,因为它只显示你不包括周末而不是假期..

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