如何聚合到组级别,按时间顺序排序和枚举组? (在 SQL 服务器中)

How to aggregate to group level, order and enumerate groups chronologically? (in SQL Server)

在医院就诊时,患者可能会接受几种不同配方的药物治疗,如下所示:

Encounter Medication Administration Adm_Num
1 A 8/31/21 11:33 AM 1
1 B 8/31/21 6:25 PM 2
1 C 9/1/21 8:55 AM 3
1 D 9/1/21 10:00 PM 4
1 B 9/2/21 11:27 AM 5
1 B 9/2/21 10:00 PM 6
1 B 9/3/21 6:15 AM 7
1 B 9/3/21 3:30 PM 8
1 D 9/3/21 8:30 PM 9

任务:对于每一次遭遇,我需要列举每一种药物的配方,像这样:

Encounter Medication Administration Adm_Num Formulation
1 A 8/31/21 11:33 AM 1 1
1 B 8/31/21 6:25 PM 2 2
1 C 9/1/21 8:55 AM 3 3
1 D 9/1/21 10:00 PM 4 4
1 B 9/2/21 11:27 AM 5 5
1 B 9/2/21 10:00 PM 6 5
1 B 9/3/21 6:15 AM 7 5
1 B 9/3/21 3:30 PM 8 5
1 D 9/3/21 8:30 PM 9 6

我需要保留管理级别的粒度,以便报告这些数据(而且我的状态很好)。

我尝试的一个策略是 CTE 来找到每种药物的药物水平值,例如第一次给药瞬间,然后将其应用于更精细的给药水平数据,如下所示:

WITH f as (
SELECT a.Encounter, a.Medication, MIN(Administration) as First_Adm,
 DENSE_RANK() OVER (PARTITION Encounter, Medication ORDER BY Administration) as Formulation
FROM a
GROUP BY a.Encounter, a.Medication
)
SELECT a.Encounter, a.Medication, a.Administration, a.Adm_Num, f.[First_Adm], f.Formulation
FROM a
INNER JOIN f ON (a.Encounter = f.Encounter AND a.Medication = f.Medication)
GROUP BY a.Encounter, a.Medication, a.Administration
ORDER BY a.Encounter, a.Medication, a.Administration

这对于前几次单次给药的药物效果很好,但它对后来再次出现的药物 B 和 D 处理不当;它从之前识别出药物 B,给它更早的 MIN(给药),并将其错误标记为配方 2,如下所示:

Encounter Medication Administration Adm_Num First_Adm Formulation
1 A 8/31/21 11:33 AM 1 8/31/21 11:33 AM 1
1 B 8/31/21 6:25 PM 2 8/31/21 6:25 PM 2
1 C 9/1/21 8:55 AM 3 9/1/21 8:55 AM 3
1 D 9/1/21 10:00 PM 4 9/1/21 10:00 PM 4
1 B 9/2/21 11:27 AM 5 8/31/21 6:25 PM 2
1 B 9/2/21 10:00 PM 6 8/31/21 6:25 PM 2
1 B 9/3/21 6:15 AM 7 8/31/21 6:25 PM 2
1 B 9/3/21 3:30 PM 8 8/31/21 6:25 PM 2
1 D 9/3/21 8:30 PM 9 9/1/21 10:00 PM 4

这很接近,但还差得远。剩下的挑战是解释重复的公式。

如何按药物配方组对管理级数据进行分组,按时间顺序排列配方(利用时间数据),并为每个配方分配一个顺序值,即使有些配方是重复的?

在此先感谢您的帮助。

这是一种“差距和孤岛”问题。

一种方法是首先使用 lag 或 lead 检查相邻行以确定数据(药物)发生变化的位置,然后将每个前面所有行的这些值相加结果中的行以生成所需的序列:

with c as (
    select *, 
      case when 
        Lag(medication) over (partition by encounter order by Administration) = medication 
      then 0 else 1 end Changed
    from t
)
select Encounter, Medication, Administration, Adm_Num,
  Sum(changed) over(partition by Encounter order by Administration) Formulation
from c;