2016-04-25 14 views
3

私は、患者が診療所を訪問したときに入力された患者のバイタル(特に血圧)を調べる必要があるクエリに取り組んでいます。私は2015年の一年間の結果を引き出しています。もちろん、何回も訪問した特定の患者がいます。最新の訪問時に入力されたバイタルのみを見る必要があります。別のわずかなねじれは、収縮期および拡張期血圧が別々に入力されていることなので、私のような結果に終わる:結果セット内の最新の日付を確認する

Patient ID  Name   DOB   Test    Results  Date 
--------------------------------------------------------------------------------- 
1000   John Smith  1/1/1955  BP - Diastolic 120   2/10/2015 
1000   John Smith  1/1/1955  BP - Systolic  70   2/10/2015 
1000   John Smith  1/1/1955  BP - Diastolic 128   7/12/2015 
1000   John Smith  1/1/1955  BP - Systolic  75   7/12/2015 
1000   John Smith  1/1/1955  BP - Diastolic 130   10/22/2015 
1000   John Smith  1/1/1955  BP - Systolic  76   10/22/2015 
9999   Jane Doe  5/4/1970  BP - Diastolic 130   4/2/2015 
9999   Jane Doe  5/4/1970  BP - Systolic  60   4/2/2015 
9999   Jane Doe  5/4/1970  BP - Diastolic 127   11/20/2015 
9999   Jane Doe  5/4/1970  BP - Systolic  65   11/20/2015 

26,000+結果がありますが、私はすべての単一の患者を通過してたときにその表示したくない明らかになります最近の結果は次のとおりです。私は私の結果は次のようになりたいのですが:

Patient ID  Name   DOB   Test   Results  Date 
--------------------------------------------------------------------------------- 
1000   John Smith  1/1/1955  BP - Diastolic 130   10/22/2015 
1000   John Smith  1/1/1955  BP - Systolic  76   10/22/2015 
9999   Jane Doe  5/4/1970  BP - Diastolic 127   11/20/2015 
9999   Jane Doe  5/4/1970  BP - Systolic  65   11/20/2015 

私は出産やその他もろもろの名前と日付を繰り返しになるだろうけど、私は主に結果列に焦点を当てています。ここで

は私のクエリです:それはのためだけれども他の答えを探しまわって後

SELECT DISTINCT 
    pd.PatientID as [Patient ID], 
    pd.PatientName as Name, 
    pd.DateOfBirth as DOB, 
    v.Test as Test, 
    v.Results as Results, 
    v.TestDate as Date 

FROM PatientDemographic pd JOIN Vitals v ON pd.PatientID = v.PatientID 

WHERE v.TestDate BETWEEN '01/01/2015' AND '12/31/2015' 
    AND v.Test LIKE 'BP%' 

ORDER BY pd.PatientID, v.TestDate 

、私は、私は特にthis linkを参照して(SELECT文でv.TestDate列のGROUP BYMAX()集約関数をやってみましたOracleと私はSQL Serverを使用しているので、構文が同じかどうか完全にはわかりません)。私のクエリは、次にように見えた:確かに

SELECT DISTINCT 
    pd.PatientID as [Patient ID], 
    pd.PatientName as Name, 
    pd.DateOfBirth as DOB, 
    v.Test as Test, 
    v.Results as Results, 
    MAX(v.TestDate) as Date 

FROM PatientDemographic pd JOIN Vitals v ON pd.PatientID = v.PatientID 

WHERE v.TestDate BETWEEN '01/01/2015' AND '12/31/2015' 
    AND v.Test LIKE 'BP%' 

GROUP BY pd.PatientID 

、私はいつもGROUP BYを使用して少し苦労しました。この特定のケースでは、患者名列をGROUP BY節に追加する必要があることを示すエラーが表示されるため、DOBを要求します。テスト名。基本的には、SELECTの文をすべてGROUP BYに追加したいと考えています。

私の直近の患者さんの診察を進めるにはどうすればよいですか?

答えて

4

一つの簡単な方法は、各テストのために、より最近のレコードを検索するROW_NUMBER()を使用しています:ゴードンが使用されるように

SELECT pd.PatientID as [Patient ID], pd.PatientName as Name, pd.DateOfBirth as DOB, 
     v.Test as Test, v.Results as Results, v.TestDate as Date 
FROM PatientDemographic pd JOIN 
    (SELECT v.*, 
      ROW_NUMBER() OVER (PARTITION BY PatientId, Test ORDER BY TestDate DESC) as seqnum 
     FROM Vitals v 
     WHERE v.TestDate BETWEEN '2015-01-01' AND '2015-12-31' AND 
      v.Test LIKE 'BP%' 
    ) v 
    ON pd.PatientID = v.PatientID 
WHERE seqnum = 1 
ORDER BY pd.PatientID, v.TestDate; 
+0

これはトリックを行ったようです!ありがとう! – EJF

1

は、私は窓関数から敬遠します。サブクエリを使用した手法は、仕事にも成し遂げることができます。

SELECT 
    ID 
    ,Name 
    ,DOB 
    ,Test 
    ,Results 
    ,[Date] 
FROM 
    Vitals AS V 
WHERE 
    V.[Date] = (SELECT MAX([Date]) FROM Vitals W WHERE W.Name = V.Name AND W.Test = 'A') 
    AND V.Test = 'A' 

UNION 

SELECT 
    ID 
    ,Name 
    ,DOB 
    ,Test 
    ,Results 
    ,[Date] 
FROM 
    Vitals AS V 
WHERE 
    V.[Date] = (SELECT MAX([Date]) FROM Vitals W WHERE W.Name = V.Name AND W.Test = 'B') 
    AND V.Test = 'B' 
+0

なぜですか? row_number()と.. =(select max()..)のパフォーマンスを比較しましたか? – Serg

+0

Nopeはまだ十分にそれらを勉強していない:)それはリストにあります。 –

1

これは、NOTは句をEXISTSほど効率的ではないであろうMS SQL 2005+

SELECT * FROM (
SELECT row_number() over(partition by pd.PatientID, v.Test order by v.TestDate desc) as rn, 
    pd.PatientID as [Patient ID], 
    pd.PatientName as Name, 
    pd.DateOfBirth as DOB, 
    v.Test as Test, 
    v.Results as Results, 
    v.TestDate as Date 
FROM PatientDemographic pd 
JOIN Vitals v ON pd.PatientID = v.PatientID 
WHERE v.TestDate BETWEEN '01/01/2015' AND '12/31/2015' 
    AND v.Test LIKE 'BP%') t 
WHERE rn = 1 
1

ウィンドウ関数のためです。

SELECT 
    pd.PatientID as [Patient ID], 
    pd.PatientName as Name, 
    pd.DateOfBirth as DOB, 
    v.Test as Test, 
    v.Results as Results, 
    v.TestDate as Date 
FROM PatientDemographic pd JOIN Vitals v ON pd.PatientID = v.PatientID 
WHERE 
    v.TestDate BETWEEN '01/01/2015' AND '12/31/2015' 
    AND v.Test LIKE 'BP%' 
    AND NOT EXISTS (
     SELECT 1 FROM Vitals as v2 where v2.PatientID = v.PatientID 
     AND V2.TestDate BETWEEN '01/01/2015' AND '12/31/2015' 
     AND v2.Test LIKE 'BP%' 
     AND v2.TestDate > v.TestDate) 
1

また、これを達成するために共通表式を使用することもできます。

 IF OBJECT_ID('tempdb..#RecentPatientVitals') IS NOT NULL 
     DROP TABLE #RecentPatientVitals; 
    GO 

    CREATE TABLE #RecentPatientVitals 
     (
      Patient_ID INT 
     , Name VARCHAR(100) 
     , DOB DATE 
     , Test VARCHAR(150) 
     , Results INT 
     , [Date] DATE 
     ); 

    INSERT INTO #RecentPatientVitals 
      (Patient_ID, Name, DOB, Test, Results, [Date]) 
    VALUES (1000, 'John Smith', '1/1/1955', 'BP - Diastolic', 120, '2/10/2015') 
    ,  (1000, 'John Smith', '1/1/1955', 'BP - Systolic', 70, '2/10/2015') 
    ,  (1000, 'John Smith', '1/1/1955', 'BP - Diastolic', 128, '7/12/2015') 
    ,  (1000, 'John Smith', '1/1/1955', 'BP - Systolic', 75, '7/12/2015') 
    ,  (1000, 'John Smith', '1/1/1955', 'BP - Diastolic', 130, '10/22/2015') 
    ,  (1000, 'John Smith', '1/1/1955', 'BP - Systolic', 76, '10/22/2015') 
    ,  (9999, 'Jane Doe', '5/4/1970', 'BP - Diastolic', 130, '4/2/2015') 
    ,  (9999, 'Jane Doe', '5/4/1970', 'BP - Systolic', 60, '4/2/2015') 
    ,  (9999, 'Jane Doe', '5/4/1970', 'BP - Diastolic', 127, '11/20/2015') 
    ,  (9999, 'Jane Doe', '5/4/1970', 'BP - Systolic', 65, '11/20/2015'); 

    SELECT * 
    FROM #RecentPatientVitals; 

    WITH PatVitals1 
       AS (SELECT Patient_ID 
          , Name 
          , DOB 
          , Test 
          , MAX(Date) AS Date 
        FROM  #RecentPatientVitals 
        GROUP BY Patient_ID 
          , Name 
          , DOB 
          , Test 
       ) , 
      PatVitals2 
       AS (SELECT Patient_ID 
          , Test 
          , Results 
          , Date 
        FROM  #RecentPatientVitals 
       ) 
     SELECT P1.Patient_ID 
       , P1.Name 
       , P1.DOB 
       , P1.Test 
       , P2.Results 
       , P1.Date 
     FROM PatVitals1 P1 
       INNER JOIN PatVitals2 P2 
       ON P2.Patient_ID = P1.Patient_ID 
        AND P2.Date = P1.Date 
        AND P2.Test = P1.Test 
     GROUP BY P1.Patient_ID 
       , P1.Name 
       , P1.DOB 
       , P1.Test 
       , P2.Results 
       , P1.Date; 
関連する問題