SQL - 在一段时间内具有多个X实例的结果

时间:2014-04-24 05:27:08

标签: sql tsql date

我正在处理一些与输血有关的实验室数据,需要提取一些在一定时间内发生的某些输血事件的统计数据。

我需要找到哪些患者在4小时内有3次或更多次输血。

我正在使用的数据每次输血都有行ID,患者ID,输血日期时间和输血产品。

例如:

row_id, patient_id, transfusion_datetime, blood_group, product
1085441, AB112, 2014-03-29 16:27:00.000, B POS, Red Cells
1087441, AB112, 2014-03-30 21:11:00.000, B POS, Red Cells
1087443, AB112, 2014-03-30 21:11:00.000, B POS, Red Cells
1088208, AB112, 2014-03-30 22:32:00.000, B POS, Red Cells
1088408, AB112, 2014-03-30 22:48:00.000, B POS, Red Cells
1088693, AB333, 2014-03-30 19:25:00.000, O POS, Red Cells
1089426, AB333, 2014-03-30 18:07:00.000, O POS, Red Cells
1088529, BB777, 2014-03-30 11:12:00.000, B NEG, Red Cells
1083933, AB333, 2014-03-30 09:31:00.000, O POS, Red Cells
1083932, AB333, 2014-03-30 07:18:00.000, O POS, Red Cells

从上面可以看出,患者AB112符合我的选择标准,因为他们在4小时内输入了4个单位(行1087441,1087443,1088208,1088408)。一旦我有了这4行ID,我就可以带回患者和输血信息。

我有一个问题,患者ID一生都在患者身上,所以他们可能在医院接受过每次输血(有些患者经常需要大量输血)。

我最初通过transfusion_datetime在某个值之间限制我的搜索。

从那里我想查看所有唯一的患者ID,然后列出每个输血,然后通过每个输入进行枚举,以查看是否在4小时内存在3个或更多,并存储这些行ID以便使用信息回来了。

但是我的问题存在,因为我不确定如何使用滚动时间跨度窗口(4小时)来迭代患者的每条记录。

请帮忙。谢谢。

编辑:使用SQL Server 2008 R2。

1 个答案:

答案 0 :(得分:0)

编辑:刚看到您对2008R2的回复。您可以执行相同的基本操作,但需要使用ROW_NUMBER()进行自联接,因为LAG()不可用。我会看看我是否能证明这一点。

示例数据:

CREATE TABLE Transfusion (
  row_id INT
, patient_id VARCHAR(5)
, transfusion_datetime DATETIME
, blood_group VARCHAR(5)
, product VARCHAR(10)
)

INSERT INTO Transfusion VALUES 
(1085441,'AB112','2014-03-29 16:27:00.000','B POS','Red Cells')
,(1087441,'AB112','2014-03-30 21:11:00.000','B POS','Red Cells')
,(1087443,'AB112','2014-03-30 21:11:00.000','B POS','Red Cells')
,(1088208,'AB112','2014-03-30 22:32:00.000','B POS','Red Cells')
,(1088408,'AB112','2014-03-30 22:48:00.000','B POS','Red Cells')
,(1088693,'AB333','2014-03-30 19:25:00.000','O POS','Red Cells')
,(1089426,'AB333','2014-03-30 18:07:00.000','O POS','Red Cells')
,(1088529,'BB777','2014-03-30 11:12:00.000','B NEG','Red Cells')
,(1083933,'AB333','2014-03-30 09:31:00.000','O POS','Red Cells')
,(1083932,'AB333','2014-03-30 07:18:00.000','O POS','Red Cells')

如果使用SQL Server 2012+,您可以使用LAG()完成此类滚动窗口查询。

;WITH cte AS (
  SELECT patient_id
        ,transfusion_datetime
        ,LAG(transfusion_datetime,2,0) OVER (PARTITION BY patient_id ORDER BY transfusion_datetime) transfusion_datetime_2_prior 
        --if the order of row_id is reliable then order the lag by that instead of transfusion_datetime
    FROM Transfusion   
)
SELECT patient_id
  FROM cte
 WHERE DATEDIFF(HOUR,transfusion_datetime_2_prior,transfusion_datetime) <=4
 GROUP BY patient_id

如果使用2005+,您可以使用ROW_NUMBER()通过自联接完成相同的操作:

;WITH cte AS (
  SELECT patient_id
        ,transfusion_datetime
        ,ROW_NUMBER() OVER (PARTITION BY patient_id ORDER BY transfusion_datetime) rn
        --if the order of row_id is reliable then order the lag by that instead of transfusion_datetime
    FROM Transfusion   
)
SELECT a.patient_id
  FROM cte a
       INNER JOIN
       cte b ON a.patient_id = b.patient_id
            AND a.rn = b.rn + 2
 WHERE DATEDIFF(HOUR,b.transfusion_datetime,a.transfusion_datetime) <=4
 GROUP BY a.patient_id

在任何一种情况下,您都可以通过将工作集首先限制为仅至少进行过三次输血的患者来看到性能提升,但我不确定查询优化器是否会自行解决这个问题。 。

这看起来如下,但我会根据实际数据进行测试。

;WITH PatientHaving3OrMore AS (
  SELECT patient_id
    FROM Transfusion
   GROUP BY patient_id
  HAVING COUNT(patient_id) > 2
)
,cte AS (
  SELECT a.patient_id
        ,transfusion_datetime
        ,ROW_NUMBER() OVER (PARTITION BY patient_id ORDER BY transfusion_datetime) rn
        --if the order of row_id is reliable then order the lag by that instead of transfusion_datetime
    FROM Transfusion a
   WHERE EXISTS(SELECT 1 FROM PatientHaving3OrMore b WHERE b.patient_id=a.patient_id)
)
SELECT a.patient_id
  FROM cte a
       INNER JOIN
       cte b ON a.patient_id = b.patient_id
            AND a.rn = b.rn + 2
 WHERE DATEDIFF(HOUR,b.transfusion_datetime,a.transfusion_datetime) <=4
 GROUP BY a.patient_id