[英]Finding events within a given timeframe with SQL
目前,我的大腦必須完全處於糊狀,因為我一直堅持下去。 我有一張桌子,上面標有某人服用某種葯物的日期,並且附有他們服葯的天數。 可以為一個人開出n
種葯物的處方,因此以下查詢的CTE是查找最大的時間范圍(葯物的填充日期+天數。)然后,我想查找至少有7種不同葯物的患者葯物在同一時間。 我在給定時間范圍內找到人們正在使用的毒品時遇到了麻煩。 這需要限制在一個人一次至少服用seven
葯物的時間范圍內。 一切正常,直到最后一部分。
來自CTE的樣本數據(fillDate + longestscript =結尾日期)
並發腳本由查詢中的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。
您是否有機會使用SQL Server 2012? 解決的辦法是在數據庫簡單得多 ,因為微軟延長了窗口功能,包括部分款項。
這個想法是要計算每個可能日期(無論是填充日期還是結束日期)的累積填充和結束次數。 然后區別是累積腳本的數量。 下面提供了每個日期的信息:
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
結果集中的每一行都有一個“下一個”,它定義了條件保持的時間段。 隨着患者從7到8到9到8到9到7並發處方,您可能會在一段時間內獲得多個記錄。
如果您有很多數據,這將是一個效率很低的查詢,因為它正在執行相當昂貴的聯接操作。 正如我所說,這在SQL Server 2012中將非常有效。
我不太確定您的架構,所以我稍作猜測,但是我注意到的第一件事是,在CTE x
,您選擇的是MAX(DaysSup)
但也按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;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.