使用日历表查找两个事件在一段时间内发生的并发天数

时间:2013-01-03 19:53:32

标签: sql sql-server sql-server-2008 tsql

我有一个结构表

(RX)

clmID         int
patid         int
drugclass     char(3)
drugName      char(25)
fillDate      date
scriptEndDate date
strength      int

和查询

;with PatientDrugList(patid, filldate,scriptEndDate,drugClass,strength)      
as      
(      
select rx.patid,rx.fillDate,rx.scriptEndDate,rx.drugClass,rx.strength      
 from rx      
)      
,      
DrugList(drugName)      
as      
(      
select x.drugClass      
from (values('h3a'),('h6h'))      
as x(drugClass)      
where x.drugClass is not null      
)      
SELECT PD.patid, C.calendarDate AS overlap_date      
 FROM PatientDrugList AS PD, Calendar AS C      
 WHERE drugClass IN ('h3a','h6h')      
  AND calendardate BETWEEN filldate AND scriptenddate      
 GROUP BY PD.patid, C.CalendarDate      
HAVING COUNT(DISTINCT drugClass) = 2     
order by pd.patid,c.calendarDate  

Calendar是一个简单的日历表,其中包含整个研究期间的所有可能日期,没有其他列。

我的查询返回看起来像

的数据

enter image description here

overlap_date表示患者在PatientDrugList CTE之后列出的两个类别中被处方药物的每一天。

我想找到每个人开具两个药物系列的连续天数。我不能使用简单的maxmin聚合,因为这不会告诉我是否有人停止了此方案然后重新开始。找到这个的有效方法是什么?

编辑:DrugList CTE中的行构造函数应该是存储过程的参数,并且为了本示例的目的进行了修改。

2 个答案:

答案 0 :(得分:1)

您正在寻找连续的日期序列。关键的观察是,如果你从日期中减去一个序列,你将得到一个恒定的日期。这将按顺序定义一组日期,然后可以对其进行分组。

select patid
  ,MIN(overlap_date) as start_overlap
  ,MAX(overlap_date) as end_overlap
  from(select cte.*,(dateadd(day,row_number() over(partition by patid order by overlap_Date),overlap_date)) as groupDate
        from cte
      )t
  group by patid, groupDate

此代码未经测试,因此可能会有一些拼写错误。

答案 1 :(得分:-2)

你需要转向某种东西,并且最大限度地减少工作量。你能否说明某人是否在约会时有两种药物?如果我正确理解你的问题,那么你将按日期进行限制。

EG示例SQL:

  declare @Temp table ( person varchar(8), dt date, drug varchar(8));

insert into @Temp values ('Brett','1-1-2013', 'h3a'),('Brett', '1-1-2013', 'h6h'),('Brett','1-2-2013', 'h3a'),('Brett', '1-2-2013', 'h6h'),('Joe', '1-1-2013', 'H3a'),('Joe', '1-2-2013', 'h6h');

with a as 
    (
    select
        person
    ,   dt
    ,   max(case when drug = 'h3a' then 1 else 0 end) as h3a
    ,   max(case when drug = 'h6h' then 1 else 0 end) as h6h
    from @Temp
    group by person, dt
    )
, b as 
    (
    select *, case when h3a = 1 and h6h = 1 then 1 end as Logic
    from a
    )
select person, count(Logic) as DaysOnBothPresriptions
from b
group by person