2017-08-10 9 views
0

高血圧の処方薬補充を検討してください。血圧に影響を与えることができる複数の薬があり、一部の患者は他の患者よりも反応が良いため、適切なものを見つけるためにそれぞれの短期試験を行う必要があります。処方箋の各試行と各試行の所要時間を特定できるようにしたい。患者がDrug A、Drug B、Drug Aをその順序で試行する場合、各試行には一意のIDが必要です。私の問題は、その第2のDrug A trialに一意のIDを割り当てることです。最初の試行と区別する方法がわかりません。カテゴリ日付順のイベントシーケンスT-SQL

 
Patient Drug FillDate DaySupply 
ABC  A  1/1/17  30 
ABC  A  2/1/17  30 
ABC  B  3/1/17  30 
ABC  A  4/1/17  30 

I want a result that is like: 

Patient Drug FillDate DaySupply Sequence 
ABC  A  1/1/17  30   1 
ABC  A  2/1/17  30   1 
ABC  B  3/1/17  30   2 
ABC  A  4/1/17  30   3
+1

使用しているデータベースにタグを付けてください。 –

答えて

2

lagを使用すると、前の行の薬物値と現在の行の値を比較できます。それらが等しくない場合は、グループ開始標識をリセットするためのケース式を使用します。続いて、連続したグループ番号を割り当てるために合計を使用します。

select patient,drug,filldate,daysupply 
,sum(col) over(partition by patient order by filldate) as sequence 
from (select t.*, 
     case when lag(drug) over(partition by patient order by filldate) = drug then 0 else 1 end as col 
     from tbl t 
    ) t 

これは、あなたがサポートlagsumウィンドウ関数であるSQL Serverのバージョンを前提としています。 MSSQLから

+0

これはうまくいきましたが、私は合計関数が薬物試験によってどのように分割されているのか分かりません。したがって、患者が3回の試行を行った場合、その患者のシーケンス列のすべての行について3を得るために、「合計(列)をシーケンスとして並べ替える」ことが期待されます。本質的には、患者のために列全体を合計するだけです。たぶん私は私が思ったようにウィンドウの機能を理解できません! – AndrewRx

0

サンプルコードは、以下の通りである:

CREATE TABLE #patientInfo (Patient VARCHAR(10), Drug varchar(10) ,FillDate date , DaySupply int) 

INSERT INTO #patientInfo 
VALUES ('abc','a','20170101',30),('abc','a','20170102',30),('abc','b','20170103',30) 

SELECT Patient, Drug, FillDate, DaySupply , ROW_NUMBER() over(partition by Patient,Drug ORDER BY Filldate) as Seq 
from #patientInfo 
0

まず、あなたが日で作業するつもりならCalendar Tableを使用して検討すべきです。それは物事を簡素化します。

create table Calendar 
(
    id int primary key identity, 
    date datetime not null 

    --various computed date attributes that we elide for now... 
) 

--populate with few years worth of days: 

declare @dt datetime 
set @dt = '1/1/2017' 

while @dt <= '12/31/2020' 
begin 

    insert Calendar select @dt 

    set @dt = dateadd(day, 1, @dt) 

end 

が故に、あなたのスキーマは、おそらくこのようなものになります。このスキーマに関して

create table Drug 
(
    id int primary key identity, 
    name nvarchar(100) not null 
) 

create table Patient 
(
    id int primary key identity, 
    name nvarchar(100) not null 
) 

create table DrugTrial 
(
    patient int foreign key references Patient, 
    drug int foreign key references Drug, 
    date int foreign key references Calendar, 
    supply int 
) 

を、あなたのサンプルデータは、次のとおりです。

insert Patient select 'ABC' 

insert Drug select 'A' 
      union select 'B' 

insert DrugTrial 
    select 1, 1, 1, 30 union 
    select 1, 1, 31, 30 union 
    select 1, 2, 61, 30 union 
    select 1, 1, 91, 30 

我々が設定された所望の結果を得ることができます単一の通常のクエリですが、わかりやすくするために、一連の共通テーブル式を使用します。

まず、前任者を持つすべての試行のセットを生成します。

with Q as 
(
    select T.* from DrugTrial S 
     cross apply 
     (
      select * from DrugTrial T 
       where T.date = S.date + S.supply and 
        T.patient = S.patient and T.drug = S.drug 
     ) T   
), 

は次に、我々はシーケンスの始めにあるトライアルのセットを計算する必要があります。これは、我々は同じ薬剤と患者との裁判の直後来る試練のすべてを望んでいることを意味します。しかし、それはすべての試行のセットだけであるので、これは簡単ですマイナス前任者(上で定義されているように、Q)を持つ試行のサブセットです。

P as 
(
    select patient, drug, date, supply from DrugTrial 
       except select patient, drug, date, supply from Q 
), 

最後に、配列を構築するために再帰クエリを使用:R

R as 
(
    select *, row_number() over (order by date) as seq from P 
     union all 
      select Q.*, S.seq from Q cross apply 
       (select * from R 
        where Q.date = R.date + R.supply 
         and Q.patient = R.patient and R.drug = Q.drug) S 

) 

ベースケースは、我々は順番にrow_number機能を増強するだけでセットP、あります我々のシーケンス番号を生成する。 Rの再帰的ケースは、各試行の後続試行(もしあれば)をRに計算するだけです。一緒にすべてを置く

select 

    Pt.id patient_id, Pt.name patient_name, 
    D.id drug_id, D.name drug_name, 
    R.supply, R.date, R.seq 

from R inner join Patient Pt on Pt.id = R.patient 
     inner join Drug D on D.id = R.drug 
     inner join Calendar C on C.id = R.date order by R.date 

は結果が得られます。

patient_id patient_name  drug_id  drug_name  supply  date seq 
----------- ---------------- ----------- ------------- ----------- ------ --- 
1   ABC    1   A    30   1  1 
1   ABC    1   A    30   31  1 
1   ABC    2   B    30   61  2 
1   ABC    1   A    30   91  3 

あなたは、ソリューション全体hereを見ることができます。コミットされていないトランザクションに包まれているため、簡単に遊ぶことができます。