2015-12-21 4 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 

Я хочу получить разницу дней от дос-ДЮ 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

Попробуйте присоединиться к вашим таблицам один раз, используя [date] МЕЖДУ [doj] И [dos]. Это даст вам одну строку за каждый день между датой начала и окончания. Вы можете отфильтровать записи, которые вы не хотите в предложении WHERE. Теперь у вас будут только нужные записи, которые вы можете использовать COUNT. –

+0

нам нужны дни разницы b/w dos и doj для каждого empid и output need includeweekenandholidayststatusdays означает, сколько дней работало сweekenstatusandholidays, без wwkenstatusandholidaysstatus означает, что нужно найти, сколько дней он работал без праздников и дней недели и выходных дней, чтобы найти holidaylistandweekendlist посмотреть в праздничный стол table.please сказать мне как написать запрос для достижения этой задачи в sql-сервере – 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=1 и Holidaystatus=1 строк, соответствующих интервалу этой строки.

Вычисляемые поля выбраны:

  • включают это общее число дней emp интервала включая выходные дни и праздники.
  • без - общее количество дней emp интервал минус выходные и праздничные дни. общий поле делает общие выходные дни и праздники не вычитается дважды.

Примечания: Этот запрос включает в себя начальное и конечные дни интервала в расчетах, поэтому интервал рассмотрен [да - дос]. Вы можете изменить предикат пункта WHERE в операции OUTER APPLY, чтобы исключить начальные, конечные или оба дня интервала.

Demo here

+0

Привет, пожалуйста, укажите без использования внешнего запроса apply.When я использовал ту же логику в заявлении об обновлении, что время наружного применения занимает больше времени и его эффективность убийства также. Для логики разумно дать запрос работать отлично. Мне нужен альтернативный запрос, пожалуйста, предоставьте его – ravi

+0

@ravi Я бы порекомендовал попробовать ответ Джейми. –

0

вы можете использовать случай в вашей COUNT, чтобы определить, является ли или не считать, что день ..

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') 
Смежные вопросы