2016-04-28 3 views
2

Я ищу решение SQL для следующей проблемы. Я хочу список сотрудников, которые более 14 дней болеют подряд.SQL получение статуса периода

Я таблицу SQL со следующим:

First_name, Last_Name, INDIRECT_ID, SHIFT_DATE 
John, Doe, Sick, 2016-01-01 
John, Doe, Sick, 2016-01-02 
John, Doe, working, 2016-01-03 
John, Doe, Sick, 2016-01-04 
John, Doe, Sick, 2016-01-05 
etc. 

Я думал сделать это, видя, если они больны для 10х (2x 5 рабочих дней) в течение двух недель. Но, возможно, для этого есть гораздо более простое решение. Но теперь я получаю повторяющиеся ответы.

select FIRST_NAME, LAST_NAME 
from (select t.* 
      ,(select count(*) 
       from LABOR_TICKET t2 
       where t2.EMPLOYEE_ID = t.EMPLOYEE_ID and 
        t2.INDIRECT_ID = t.INDIRECT_ID and 
        t2.SHIFT_DATE >= t.SHIFT_DATE and 
        t2.SHIFT_DATE < DATEADD(day, 14, t.SHIFT_DATE)) NumWithin14Days 
     from LABOR_TICKET t 
     where SHIFT_DATE between '2016-01-01' and '2016-04-01' 
    ) LABOR_TICKET 
    INNER JOIN 
         EMPLOYEE ON LABOR_TICKET.EMPLOYEE_ID = EMPLOYEE.ID 

where NumWithin14Days >= 10 AND INDIRECT_ID = 'SICK' 

ответ

0

Попробуйте это Сначала нужно создать все дни интервалы 14 между От даты и до настоящего времени. Затем проверьте количество «больных» - 14 в каждом интервале для каждого сотрудника.

DECLARE @ST_DATE DATE='2016-01-01' 
     ,@ED_DATE DATE='2016-04-01' 
;WITH CTE_DATE AS (

    SELECT @ST_DATE AS ST_DATE,DATEADD(DAY,13,@ST_DATE) AS ED_DATE 
    UNION ALL 
    SELECT DATEADD(DAY,1,ED_DATE),DATEADD(DAY,14,ED_DATE) 
    FROM CTE_DATE 
    WHERE DATEADD(DAY,14,ED_DATE) <= @ED_DATE 
) 
SELECT FIRST_NAME, LAST_NAME 
FROM CTE_DATE 
    INNER JOIN LABOR_TICKET ON SHIFT_DATE BETWEEN ST_DATE AND ED_DATE 
WHERE INDIRECT_ID = 'Sick' 
GROUP BY FIRST_NAME, LAST_NAME 
HAVING COUNT(*) >= 14 
+0

Спасибо! Он отлично работает в SQL Management Studio, но как я могу реализовать этот код в Microsoft SQL Server Report Builder, поэтому пользователь может выбрать дату начала и окончания. У меня есть эта ошибка: «Типы не совпадают между якорем и рекурсивной частью в столбце« St_DATE »рекурсивного« CTE_DATE » – Scaver

+1

Найденное решение. – Scaver

0

Псевдо код, чтобы дать вам представление для всех сотрудников

, если у вас есть календарную таблицу, как показано ниже

create table dates 
(
datetime date 
) 

insert into dates 
select '2016-01-01' 
union all 
select '2016-01-02' 

Теперь вы можете щелкнуть левой присоединиться к этому с основной таблицей как

select 
mt.firstname,dt.date,count(indirect_id) 
from 
datestable dt 
left join 
maintable mt 
on mt.date=dt.date 
and mt.indirect_id='sick' 
group by mt.firstname,dt.date 
having count(indirect_id)>=14 
order by dt.date 
0

вы должны были выбросить больше данных образца.

попробуйте это, (я уверен, что он будет работать с другими данными примера), мало что есть, чтобы фильтровать данные.

declare @t table(First_name varchar(50), Last_Name varchar(50), INDIRECT_ID varchar(50), SHIFT_DATE date) 
insert into @t values 
('John', 'Doe', 'Sick', '2016-01-01') 
,('John', 'Doe', 'Sick', '2016-01-02') 
,('John','Doe','working','2016-01-03') 
,('John', 'Doe', 'Sick', '2016-01-04') 
,('John', 'Doe', 'Sick', '2016-01-05') 

declare @name varchar(50)='John' 
declare @month int=1 
;With CTE as 
(
    select top 1 First_name,Last_Name,SHIFT_DATE,1 rn from @T where [email protected] 
    and INDIRECT_ID='Sick' order by SHIFT_DATE 
    union all 
    select t.First_name,t.Last_Name,t.SHIFT_DATE, rn+1 from @T t 
    inner join cte c on t.First_name=c.First_name 
where INDIRECT_ID='Sick' 
    and t.SHIFT_DATE=DATEADD(day,1,c.SHIFT_DATE) 
    and t.SHIFT_DATE<='2016-01-31' 
) 

select * from CTE where rn>=14 
0
declare @t table(First_name varchar(50), Last_Name varchar(50), INDIRECT_ID varchar(50), SHIFT_DATE date) 
insert into @t values 
('John', 'Doe', 'Sick', '2016-01-01') 
,('John', 'Doe', 'Sick', '2016-01-02') 
,('John','Doe','working','2016-01-03') 
,('John', 'Doe', 'Sick', '2016-04-04') 
,('John', 'Doe', 'Sick', '2016-05-05') 

select s.* 
     ,u.* 
     ,Sickdays = 
     case 
     when s.indirect_id = 'Sick' and u.indirect_id = 'Sick' then datediff(dd,u.shift_date,s.shift_date) 
     else 0 
     end 
from 
(
select t.*, 
     row_number() over(partition by last_name,first_name order by shift_date desc) rn 
from @t t 
) s 
join  
(select t.*, 
     row_number() over(partition by last_name,first_name order by shift_date desc) rn 
from @t t 
) u on s.last_name = u.last_name and s.first_name = u.first_name and s.rn = u.rn - 1 
where 
     case 
     when s.indirect_id = 'Sick' and u.indirect_id = 'Sick' then datediff(dd,u.shift_date,s.shift_date) 
     else 0 
     end > 13 
+0

Пожалуйста, обратите внимание, что даты локализованы в UK, т. Е. Yyyymmdd в моих тестовых данных. Излишне говорить, что было бы намного безопаснее, если бы у вас был идентификатор сотрудника, чтобы присоединиться к нему, и в реальном мире вам, вероятно, придется сообщить о болезни по рабочим дням, что не так просто. –

Смежные вопросы