我需要有关查询的帮助,该查询将填补一些缺失的时间(以分钟为单位)的空白,并保持当前状态。我在医院工作,我们试图在任何给定的时间了解医院急诊科的瓶颈。
我表中的数据如下所示:
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
等,直到我达到“等待分类”的下一个状态 ...然后我需要针对该状态的每一分钟执行相同的操作,直到下一个...等等。等
如何编写不执行循环的查询?有数百万条记录(和分钟)要考虑,所以我需要一个便宜的查询。
感谢您的帮助!
答案 0 :(得分:0)
您可以在此处使用递归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()
映射后续事件。将该最大值减去1表示最大递归级别。
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;
答案 1 :(得分:0)
您是否不认为插入这些分钟将使您的数百万行变得更多,其中包含大量冗余数据的行呢?目的是什么? (也许某种与显示相关的工作?)。
无论如何,如果您认为必须这样做,则可以通过交叉应用来实现。即:
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;
答案 2 :(得分:0)
<link type="stylesheet" href="yourstyle.css" />
<style>
* {
color: #333 !important;
}
</style>