2016-04-25 77 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 

四處尋找其他的答案,我試着做一個GROUP BYMAX()聚合函數在SELECT聲明v.TestDate柱(我是專門引用this link,雖然這對後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()和.. =(選擇max()..)的性能? – Serg

+0

沒有,只是沒有足夠的研究:)它是在名單上。 –

1

這是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

窗口函數不會被視爲有效的NOT EXISTS子句。我想建議不使用窗口函數更快的解決方案:

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;