我的大脑此刻必须完全糊涂,因为我坚持这一点。我有一张桌子上有一个日期,有人被给予了药物,这是他们服用药物的天数。一个人可以被处方n
个药物,因此以下查询的CTE是找到最大的时间范围(药物的填写日期+天数供应。)然后我想找到那些人在至少七种不同的药物同时使用。我无法找到人们在给定时间内使用的药物。这需要限制在一个人同时服用至少seven
药物的时间段内。一切正常,直到最后一部分。
来自CTE的样本数据(fillDate + longestscript = endingDate)
并发脚本由查询中的count(distinct rx.drugname)
确定
;with cte
as
(
select rx.patid
,rx.fillDate
,MAX(rx.dayssup) as longestScript
,DATEADD(day,cast(rx.dayssup as int),rx.filldate) as endingDate
from rx
group by rx.patid, rx.fillDate,rx.daysSup
),
startends as (
select patid, FillDate as thedate, 1 as isstart 0 as isend
from CTE union all
select patid, EndingDate as thedate, 0 as isstart, 1 as isend
from CTE
),
cums as (
select se.*,
(select min(thedate) from startends se2 where se2.filledate > se.filldate) as nextdate,
(select SUM(isstart) from startends se2 where se2.filldate <= se.filldate) as cumstarts,
(select SUM(isend) from startends se2 where se2.filldate <= se.filldate) as cumends
from startends se
)
select *
from cums
where sumstarts - cumends >= 7
您可以在第二个查询中看到每个患者多次出现,fillDate和endingDate之间的时间跨度不同。如何编写查询以获得第二个屏幕截图第一行重复的九种药物? SQL Server 08 r2是我的dbms。
答案 0 :(得分:2)
您是否正在使用SQL Server 2012?该解决方案在该数据库中很多更简单,因为Microsoft扩展了窗口函数以包含部分和。
这个想法是计算每个可能日期的累积填充和结束次数 - 无论是填写日期还是结束日期。然后差异是累积脚本的数量。以下提供了每个日期的信息:
with cte as (<your query>),
startends as (
select patid, FillDate as thedate, 1 as isstart 0 as isend
from CTE union all
select patid, EndingDate as thedate, 0 as isstart, 1 as isend
from CTE
),
cums as (
select se.*,
(select min(thedate) from startends se2 where se2.filledate > se.filldate) as nextdate,
(select SUM(isstart) from startends se2 where se2.filldate <= se.filldate) as cumstarts,
(select SUM(isend) from startends se2 where se2.filldate <= se.filldate) as cumends
from startends se
)
select *
from cums
where cumstarts - cumends >= 7
结果集中的每一行都有一个&#34; nextdate&#34;它定义了条件成立的时间段。您可能会在一段时间内获得多个记录,因为患者会从7到8到9到8到9到7个并发处方。
如果您有大量数据,这将是一个相当低效的查询,因为它正在进行相当昂贵的连接操作。但正如我所说,这在SQL Server 2012中会非常有效。
答案 1 :(得分:1)
我不太确定你的架构,所以我要稍微猜测一下,但我注意到的第一件事就是在你的CTE x
中,你选择的是MAX(DaysSup)
,还要按{{1}进行分组,使最大冗余。
但是,我并不认为这与您的问题有关。我个人会采取不同的方法来解决这个问题。我假设你有一个表格:
dayssup
所以你可以按照以下方式做点什么:
CREATE TABLE rx
( PatID INT,
FillDate DATE,
Dayssup INT,
DrugName VARCHAR(50)
)
这将列出每位患者服用药物的所有日期,而不是范围,因此您可以使用以下内容:
SELECT rx.PatID,
rx.FillDate,
rx.DrugName,
[DateTaken] = DATEADD(DAY, v.Number, FillDate)
FROM RX
INNER JOIN master..spt_values v
ON v.Number BETWEEN 0 AND rx.DaysSup
AND v.Type = 'P'
我已经介绍的第一部分,第二部分简单地将结果限制在7种或更多种药物的所有日期。第三个CTE按连续日期对每个患者进行分组,最后一个CTE将每个患者的最小值和最大值分组。
如果您需要在每个日期获取药物清单,您可以加入cte WITH x AS
( SELECT rx.PatID,
rx.FillDate,
rx.DrugName,
[DateTaken] = DATEADD(DAY, v.Number, FillDate)
FROM rx
INNER JOIN master..spt_values v
ON v.Number BETWEEN 0 AND rx.DaysSup
AND v.Type = 'P'
), y AS
( SELECT x.PatID,
x.DateTaken,
DrugsTaken = COUNT(DISTINCT x.DrugName)
FROM x
GROUP BY x.PatID, x.DateTaken
HAVING COUNT(DISTINCT x.DrugName) >= 7
), z AS
( SELECT *,
GroupID = DATEDIFF(DAY, - ROW_NUMBER() OVER(PARTITION BY PatID ORDER BY DateTaken DESC), DateTaken)
FROM y
)
SELECT z.PatID,
[MostConccurent] = MAX(z.DrugsTaken),
[DateStarted] = MIN(z.DateTaken),
[DateEnded] = MAX(z.DateTaken)
FROM z
GROUP BY z.PatID, z.GroupID;
:
x