Заполнение промежутков времени - PullRequest
0 голосов
/ 01 октября 2018

Мне нужна помощь с запросом, который заполнит некоторые пропущенные промежутки времени (в минутах), а также сохранит текущий статус.Я работаю в больнице, и мы пытаемся понять узкие места в отделении неотложной помощи больницы, в любой момент.
Данные в моей таблице выглядят так:

Patient_Id      event_time             Event_Status_Name
98676249    2018-09-24 18:39:00.000    Expected
98676249    2018-09-24 19:17:00.000    Waiting for Triage
98676249    2018-09-24 19:28:00.000    In Triage
98676249    2018-09-24 19:29:00.000    Waiting for Room
98676249    2018-09-24 19:45:00.000    Waiting for Provider
98676249    2018-09-24 19:48:00.000    In Process
98676249    2018-09-24 21:02:00.000    Await IP Orders
98676249    2018-09-24 22:59:00.000    Await IP Bed
98676249    2018-09-25 21:44:00.000    Ready for Admit

Это в основном говорит мнев какое время пациент вошел в определенный статус.Однако мне нужно заполнить недостающие минуты и сохранить статус, в котором они находятся. Например, с 2018-09-24 18: 39: 00.000 до 2018-09-24 19: 16: 00.000пациент находился в «ожидаемом» состоянии.Просто используя первый статус в качестве примера, мой желаемый результат запроса должен выглядеть следующим образом:

Patient_Id  event_time             Event_Status_Name
98676249    2018-09-24 18:39:00.000    Expected
98676249    2018-09-24 18:40:00.000    Expected
98676249    2018-09-24 18:41:00.000    Expected
98676249    2018-09-24 18:42:00.000    Expected
98676249    2018-09-24 18:43:00.000    Expected
98676249    2018-09-24 18:44:00.000    Expected
98676249    2018-09-24 18:45:00.000    Expected
98676249    2018-09-24 18:46:00.000    Expected
98676249    2018-09-24 18:47:00.000    Expected
98676249    2018-09-24 18:48:00.000    Expected

и т. Д., И т. Д., Пока я не достигну следующего состояния «ожидание сортировки» ... и затемМне нужно делать то же самое, для каждой минуты этого статуса, до следующей ... и т. Д.и т.д.

Как мне написать запрос, который делает это, без использования цикла?Есть миллионы записей (и минут) для учета, поэтому мне нужен недорогой запрос для этого.

Спасибо за вашу помощь!

Ответы [ 3 ]

0 голосов
/ 02 октября 2018

Не думаете ли вы, что вставка этих минут сделает ваши миллионы строк намного более миллионами строк с большим количеством избыточных данных в нем?В чем может быть цель?(Может быть, какая-то работа, связанная с показом?).

В любом случае, если вы думаете, что должны, то вы можете сделать это с помощью некоторого перекрестного обращения.т.е.:

WITH tally
AS (SELECT TOP (1440 * 10)
           ROW_NUMBER() OVER (ORDER BY t1.object_id) AS N
    FROM master.sys.all_columns t1
        CROSS JOIN master.sys.all_columns t2),
     missedMinutes
AS (SELECT *
    FROM dbo.Patients t1
        CROSS APPLY
    (
        SELECT DATEDIFF(MINUTE, t1.event_time, MIN(t2.event_time))
        FROM Patients t2
        WHERE t1.Patient_Id = t2.Patient_Id
              AND t2.event_time > t1.event_time
    ) t(missed)
        CROSS APPLY
    (
        SELECT TOP (ISNULL(missed, 1) - 1)
               DATEADD(MINUTE, N, t1.event_time)
        FROM dbo.Patients t2
            CROSS JOIN tally
        WHERE t2.Patient_Id = t1.Patient_Id
              AND t1.event_time = t2.event_time
        ORDER BY tally.N
    ) tt(missing) )
SELECT Patient_Id,
       missing AS event_time,
       Event_Status_Name
INTO #missInsert
FROM missedMinutes
ORDER BY event_time;

SELECT *
FROM #missInsert;

DROP TABLE #missInsert;

Демоверсия DBFiddle здесь

0 голосов
/ 02 октября 2018
Declare @calc1 as table (Paitent_event_sno int,Patient_Id int, event_time DateTime,Event_Status_Name varchar(100))                                      
insert into @calc1 Select Paitent_event_sno = ROW_NUMBER() Over(partition by Patient_Id order by event_time Asc), *  from @Hospital 
Declare @final as table (Patient_Id int, event_time DateTime,Event_Status_Name varchar(100))

Declare @Pno int, @Sno int
declare cur CURSOR LOCAL for 
Select Distinct Patient_id from @calc1
open cur
fetch next from cur into @Pno
while @@FETCH_STATUS = 0 
BEGIN

declare cur2 CURSOR LOCAL for 
Select Distinct Paitent_event_sno from @calc1  where  Patient_Id =  @Pno 
open cur2
fetch next from cur2 into @Sno
while @@FETCH_STATUS = 0 
BEGIN

        declare @starttime datetime , @endtime datetime, @eventtime datetime
        insert into @final
        Select Patient_Id, event_time , Event_Status_Name from @calc1 
        where Patient_Id =   @Pno and   Paitent_event_sno = @Sno

        Select @starttime = event_time , @eventtime = event_time from  @calc1 where Patient_Id =   @Pno and   Paitent_event_sno = @Sno

        Select @endtime = event_time from @calc1 where Patient_Id =   @Pno and   Paitent_event_sno = @Sno+1


        set @eventtime = dateadd(mi,1,@eventtime )

        while @eventtime < @Endtime
        begin
        insert into @final
        Select Patient_Id,  @eventtime,Event_Status_Name   
        from @calc1 where Patient_Id =   @Pno and   
        Paitent_event_sno = @Sno

        set @eventtime = dateadd(mi,1,@eventtime )
        end                    

        fetch next from cur2 into @Sno
        END
        close cur2
        deallocate cur2

        fetch next from cur into @pno
        END
        close cur
        deallocate cur

        Select * from @final
0 голосов
/ 01 октября 2018

Вы можете использовать рекурсивный CTE здесь.В качестве привязки получите все существующие строки вместе с их номером, упорядоченным по метке времени на пациента.Затем выберите строку из привязки, применяя к ним следующее событие - через номер строки и пациента - и убедитесь, что следующая минута меньше метки времени последующего события.

WITH cte
AS
(
SELECT x.patient_id,
       x.event_time,
       x.event_status_name,
       x.rn
       FROM (SELECT t.patient_id,
                    t.event_time,
                    t.event_status_name,
                    row_number() OVER (PARTITION BY t.patient_id
                                       ORDER BY t.event_time) rn
                    FROM elbat t) x
UNION ALL
SELECT c.patient_id,
       dateadd(minute, 1, c.event_time),
       c.event_status_name,
       c.rn
       FROM cte c
            CROSS APPLY (SELECT y.patient_id,
                                y.event_time
                                FROM (SELECT t.patient_id,
                                             t.event_time,
                                             row_number() OVER (PARTITION BY t.patient_id
                                                                ORDER BY t.event_time) rn
                                             FROM elbat t) y
                                     WHERE y.rn = c.rn + 1) x
        WHERE x.patient_id = c.patient_id
              AND x.event_time > dateadd(minute, 1, c.event_time)
)
SELECT *
       FROM cte c
       ORDER BY c.patient_id,
                c.event_time
OPTION (MAXRECURSION 1364);

Существуетхотя одна проблема.Ваши пробелы настолько велики, что максимальный уровень рекурсии в 100 превышен.Вы можете увеличить его, используя OPTION (MAXRECURSION n).Чтобы найти подходящий n, вы можете запросить данные, чтобы найти максимальную разницу последующих событий в минутах.Опять же это использует row_number() для отображения последующих событий.Возьмите этот максимум минус единицу для максимального уровня рекурсии.

WITH cte
AS
(
SELECT t.patient_id,
       t.event_time,
       row_number() OVER (PARTITION BY t.patient_id
                          ORDER BY event_time) rn
       FROM elbat t
)
SELECT max(datediff(minute, c2.event_time, c1.event_time)) - 1
       FROM cte c1
            INNER JOIN cte c2
                       ON c2.patient_id = c1.patient_id
                          AND c2.rn = c1.rn - 1;

db <> скрипка

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...