2017-02-14 5 views
1

Первое сообщение здесь, но может ли кто-нибудь помочь или помочь мне понять следующую проблему. Для следующей таблицы «Patient_Table», как я могу узнать общее количество дней, ,Microsoft SQL Server вычисляет общее время между последовательными событиями

ID Patient_ID  Listing_Number  Date    Status 
----------------------------------------------------------------- 
1  22    1     01/01/2016  Healthy 
2  22    2     01/11/2016  Sick 
3  34    1     01/13/2016  Healthy 
4  22    3     01/20/2016  Healthy 
5  22    4     01/22/2016  Sick 
6  22    5     01/23/2016  Healthy 

Ниже приведена моя логика до сих пор, но я не уверен в правильном синтаксисе.

declare 
@count  int = 1, 
@Days_sicks int = 0 

while @count <= (select max (Listing_number) from Patient_Table where Patient_id = '22') 

begin 
    case 
    when (select status from Patient_Table where Patient_id = '22' and Listing_number = @count) = 'Sick' 
    then @Days_sicks = @Days_sicks + datediff('dd', (select min date from Patient_Table where patient_id = 22 and listing_number > @count and status != 'Sick'), (select date from patient_table where patient_id = 22 and listing_number = @count) 
    else @Days_sicks 
    end as Days_sicks 

set @Count = @Count + 1 
END; 

Я также попытался это одно, но это не работает очень хорошо, и я имею проблему с группой по статье

SELECT t1.patient_id, 
    DATEDIFF(dd, 
     t1.date, 
     (SELECT MIN(t3.date) 
     FROM Patient_Table t3 
     WHERE t3.patient_id = t1.patient_id 
     AND t3.date> t1.date) as Days_sicks 
    ) 
FROM Patient_Table t1 
WHERE EXISTS(
    SELECT 'NEXT' 
    FROM Patient_Table t2 
    WHERE t2.patient_id = t1.patient_id 
    AND t2.date> t1.date 
    AND t2.status != 'sick') 
    and t1.patient_id = '22' 

желаемого результата

Patient id Days_sicks 
22   10 
+0

Какова логика quesiton, min (date) до max (date), где status = 'Sick'? – McNets

+0

Не могли бы вы указать версию sql-сервера – AldoRomo88

+0

@why 10? если это не будет? – CodingYoshi

ответ

2

Используйте функцию lead(), а затем агрегацию:

select patient_id, 
     sum(datediff(day, date, coalesce(next_date, getdate()))) 
from (select pt.*, 
      lead(date) over (partition by patient_id order by date) as next_date 
     from patient_table pt 
    ) pt 
where status = 'Sick' 
group by patient_id; 

Примечание: Если кто-то в настоящее время болен, тогда используется текущая дата для окончания «больного» состояния.

Кроме того, это будет работать, если пациент болен при нескольких посещениях.

+0

Спасибо, Гордон. Это сработало отлично! –

0
Select s.Patient_ID, 
    sum(datediff(day, s.Date, coalesce(h.date, getdate()) totalDaysSick 
From table s left join table h 
    on h.Patient_ID = s.Patient_ID 
    and h.Status = 'Healthy' 
    and s.Status ='Sick' 
    and h.Date = (Select Min(date) from table 
        where Patient_ID = s.Patient_ID 
        and Date > s.Date) 
Group By Patient_Id 
0

Вы можете использовать Lag оконной функции и порядок по дате, а затем сделать DATEDIFF найти количество дней между текущей и предыдущей датой. Затем сделайте сумму на количество дней:

select 
    sickdays.Patient_ID 
    ,Sum(sickdays.DayNums) as SickDays 
from 
    (select 
      Patient_ID 
      ,Datediff(day, Lag([Date], 1, null) over (order by [Date]), [Date]) as DayNums 

     from Patient 
     where Patient_ID = 22 
     and Status = 'Sick' 
     group by Patient_ID 
        ,Date) as sickdays 
where 
    sickdays.DayNums is not null 
group by sickdays.Patient_ID