T-SQL 汇总和分组的逻辑

T-SQL logic for roll up and group by

我有一个问题要根据以下逻辑折叠或汇总数据。 我该如何实施?

允许将发作浓缩为单个连续护理发作的逻辑是出院代码 22,然后是同一天的入院代码 4。

continuous care implementation update

EPN--是一个business_key.

episode_continuous_care_key是人工键,可以是行号函数

下面是table结构。

            drop table #source
            CREATE TABLE #source(patidid varchar(20),epn int,preadmitdate datetime,adminttime varchar(10),
            admitcode varchar(10),datedischarge datetime,disctime varchar(10),disccode varchar(10))
            INSERT INTO #source VALUES
             (1849,1,'4/23/2020','7:29',1,'7/31/2020','9:03',22)
            ,(1849,2,'7/31/2020','11:00',4,'7/31/2020','12:09',22)
            ,(1849,3,'7/31/2020','13:10',4,'8/24/2020','10:36',10)
            ,(1849,4,'8/26/2020','12:25',2,null,null,null)
            ,(1850,1,'4/23/2020','7:33',1,'6/29/2020','7:30',22)
            ,(1850,2,'6/29/2020','9:35',4,'7/8/2020','10:51',7)
            ,(1850,3,'7/10/2020','11:51',3,'7/29/2020','9:12',7)
            ,(1850,4,'7/31/2020','11:00',2,'8/6/2020','10:24',22)
            ,(1850,5,'8/6/2020','12:26',4,null,null,null)
            ,(1851,1,'4/23/2020','7:35',1,'6/24/2020','13:45',22)
            ,(1851,2,'6/24/2020','15:06',4,'9/24/2020','15:00',2)
            ,(1851,3,'12/4/2020','8:59',0,null,null,null)
            ,(1852,1,'4/23/2020','7:37',1,'7/6/2020','11:15',20)
            ,(1852,2,'7/8/2020','10:56',0,'7/10/2020','11:46',2)
            ,(1852,3,'7/10/2020','11:47',2,'7/28/2020','13:16',22)
            ,(1852,4,'7/28/2020','15:17',4,'8/4/2020','11:37',22)
            ,(1852,5,'8/4/2020','13:40',4,'11/18/2020','15:43',2)
            ,(1852,6,'12/2/2020','15:23',2,null,null,null)
            ,(1853,1,'4/23/2020','7:40',1,'7/1/2020','8:30',22)
            ,(1853,2,'7/1/2020','14:57',4,'12/4/2020','12:55',7)
            ,(1854,1,'4/23/2020','7:44',1,'7/31/2020','13:07',20)
            ,(1854,2,'8/3/2020','16:30',0,'8/5/2020','9:32',2)
            ,(1854,3,'8/5/2020','10:34',2,'8/24/2020','8:15',22)
            ,(1854,4,'8/24/2020','10:33',4,'12/4/2020','7:30',22)
            ,(1854,5,'12/4/2020','9:13',4,null,null,null)

那张 Excel sheet 图像几乎没有说明您的数据库设计,所以我发明了我自己的版本,它或多或少类似于您的图像。通过适当的数据库设计,解决方案的第一步应该是不需要的...

  1. 反转时间戳信息,使入院时间戳和出院时间戳成为一列。
    我为此操作使用了一个常见的 table 表达式 Log1
  2. 使用代码过滤掉连续护理期的开始。这些是招生,在我的数据库设计中用Code.IsAdmission = 1标记。
    还可以使用 lead() 函数将下一个周期开始添加为另一列。
    这些是 Log2 的所有操作。
  3. 添加行号作为持续护理键。
    使用下一个周期开始日期,找到当前连续周期结束日期 cross apply.
    使用 coalesce() 函数将空期间结束日期替换为当前日期。
    使用 datediff() 函数计算连续护理期持续时间的差异。

示例数据

create table Codes
(
  Code int,
  Description nvarchar(50),
  IsAdmission bit
);

insert into Codes (Code, Description, IsAdmission) values
( 1, 'First admission', 1),
( 2, 'Re-admission', 1),
( 4, 'Campus transfer IN', 0),
(10, 'Trial visit', 0),
(22, 'Campus transfer OUT', 0);

create table PatientLogs
(
  PatientId int,
  AdmitDateTime smalldatetime,
  AdmitCode int,
  DischargeDateTime smalldatetime,
  DischargeCode int
);

insert into PatientLogs (PatientId, AdmitDateTime, AdmitCode, DischargeDateTime, DischargeCode) values
(1849, '2020-04-23 07:29', 1, '2020-07-31 09:03', 22),
(1849, '2020-07-31 11:00', 4, '2020-07-31 12:09', 22),
(1849, '2020-07-31 13:10', 4, '2020-08-24 10:36', 10),
(1849, '2020-08-26 12:25', 2, null, null);

解决方案

with Log1 as
(
  select updt.PatientId,
         case updt.DateTimeType
           when 'AdmitDateTime' then updt.AdmitCode
           when 'DischargeDateTime' then updt.DischargeCode
         end as Code,
         updt.LogDateTime,
         updt.DateTimeType
  from PatientLogs pl
  unpivot (LogDateTime for DateTimeType in (AdmitDateTime, DischargeDateTime)) updt
),
Log2 as (
  select l.PatientId,
         l.Code,
         l.LogDateTime,
         lead(l.LogDateTime) over(partition by l.PatientId order by l.LogDateTime) as LogDateTimeNext
  from Log1 l
  join Codes c
    on c.Code = l.Code
  where c.IsAdmission = 1
)
select la.PatientId,
       row_number() over(partition by la.PatientId order by la.LogDateTime) as ContCareKey,
       la.LogDateTime as AdmitDateTime,
       coalesce(ld.LogDateTime, convert(smalldatetime, getdate())) as DischargeDateTime,
       datediff(day, la.LogDateTime, coalesce(ld.LogDateTime, convert(smalldatetime, getdate()))) as ContStay
from Log2 la -- log admission
outer apply ( select top 1 l1.LogDateTime
              from Log1 l1
              where l1.PatientId = la.PatientId
                and l1.LogDateTime < la.LogDateTimeNext
              order by l1.LogDateTime desc ) ld -- log discharge
order by la.PatientId,
         la.LogDateTime;

结果

PatientId  ContCareKey  AdmitDateTime     DischargeDateTime  ContStay
---------  -----------  ----------------  -----------------  --------
1849       1            2020-04-23 07:29  2020-08-24 10:36   123
1849       2            2020-08-26 12:25  2021-02-03 12:49   161

Fiddle 通过中间结果查看实际操作。

这是一个包含主键和外键关系的 T-SQL 解决方案。

为了让它更真实一些,我添加了一个简单的“患者”table。

我把你所有的“代码”都放在一个 table 中,这样应该更容易管理代码。

我不明白你的“持续护理”概念的目的,所以我只是在 Admission table 中添加了一个“是第一个”二元列。 您也可以考虑添加一些关于正在接受治疗的患者的医疗状况。

CREATE SCHEMA Codes

开始

开始

创建 TABLE dbo.Code ( codeNr int NOT NULL, 说明 nvarchar(50), 约束 Code_PK 主键(codeNr) ) 去

创建 TABLE dbo.Patient ( patientNr int NOT NULL, 生日日期不为空, firstName nvarchar(max) 不为空, lastName nvarchar(max) 不为空, 约束 Patient_PK 主键(patientNr) ) 去

创建 TABLE dbo.Admission ( admitDateTime 时间不为空, patientNr int NOT NULL, 承认代码 int, 是第一位, 约束 Admission_PK 主键(patientNr,admitDateTime) ) 去

创建 TABLE dbo.Discharge ( dischargeDateTime 时间不为空, patientNr int NOT NULL, dischargeCode int NOT NULL, 约束 Discharge_PK 主键(patientNr,出院日期时间) ) 去

ALTER TABLE dbo.Admission 添加约束 Admission_FK1 外键 (patientNr) 参考 dbo.Patient (patientNr) 删除时无操作 更新时无操作 去

ALTER TABLE dbo.Admission 添加约束 Admission_FK2 外键 (admitCode) 参考 dbo.Code (codeNr) 删除时无操作 更新时无操作 去

ALTER TABLE dbo.Discharge 添加约束 Discharge_FK1 外键 (patientNr) 参考 dbo.Patient (patientNr) 删除时无操作 更新时无操作 去

ALTER TABLE dbo.Discharge 添加约束 Discharge_FK2 外键 (dischargeCode) 参考 dbo.Code (codeNr) 删除时无操作 更新时无操作 去

开始