0

我的大脑此刻一定是完全糊状的,因为我被困在这上面。我有一张表格,上面列出了某人服用药物的日期,以及他们服用药物的天数。可以为一个人开出n多种药物,因此以下查询的 CTE 是找到最大的时间范围(药物的填充日期 + 供应天数。)然后我想找到至少服用七种不同药物的人同时。我很难找到人们在给定时间范围内服用的药物。这需要限制在一个人至少seven一次吸毒的时间段内。直到最后一部分,一切正常。

来自 CTE 的样本数据(fillDate + longscript =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。

4

2 回答 2

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

结果集中的每一行都有一个“nextdate”,它定义了条件成立的时间段。当患者从 7 到 8 到 9 到 8 到 9 到 7 个并发处方时,您可能最终会得到多个记录。

如果你有很多数据,这将是一个相当低效的查询,因为它正在执行相当昂贵的连接操作。不过,正如我所说,这在 SQL Server 2012 中会非常有效。

于 2012-11-12T19:55:45.990 回答
1

我不太确定您的架构,所以我稍微猜测一下,但是我注意到的第一件事是,在您的 CTEx中,您正在选择MAX(DaysSup)但也分组 by dayssup,从而使 max 冗余。

但是,我真的不认为这与您的问题有关。我个人会采取不同的方法来解决这个问题。我假设您有一个表格,如下所示:

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'

这将列出每位患者服用药物的所有日期,而不是一个范围,因此您可以使用以下内容:

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;

我已经介绍的第一部分,第二部分只是将结果限制在包含 7 种或更多药物的所有日期。第三个 CTE 按连续日期对每位患者进行分组,最后一个 CTE 获取每个日期的最小值和最大值。

如果您需要在每个日期服用的药物清单,您可以重新加入 cte x

SELECT  z.PatID, 
        x.DrugName,
        [MostConccurent] = MAX(z.DrugsTaken),
        [DateStarted] = MIN(z.DateTaken),
        [DateEnded] = MAX(z.DateTaken)
FROM    z
        INNER JOIN x
            ON x.PatID = z.PatID
            AND x.DateTaken = z.DateTaken
GROUP BY z.PatID, z.GroupID, x.DrugName;
于 2012-11-12T20:19:11.190 回答