2014-11-02 106 views
0

我試圖解決以下挑戰:如何使用SQL在同一列中查找日期之間的差異?

1)如果患者在48小時內訪問ER,我想標記爲1。 2)如果同一患者在48小時後再次訪問ER,我想標記爲2

3)每個後續訪問必須標記爲3,4,5等48小時後。

這裏是我的表是什麼樣子:

PATIENT_ID ADMIT_DATE LOCATION 
    ---------- ---------- -------- 
    33   1/10/2014 ER 
    33   1/11/2014 ER 
    33   1/15/2014 ER 
    33   1/17/2014 ER 
    45   2/20/2014 OBS 
    45   2/21/2014 OBS 
    45   2/25/2014 OBS 
    45   2/30/2014 OBS 
    45   2/32/2014 OBS 

這裏是理想的結果應該是什麼樣子:

PATIENT_ID ADMIT_DATE LOCATION FLAG 
---------- ---------- -------- ---- 
33   1/10/2014  ER  1 
33   1/15/2014  ER  2 
33   1/17/2014  ER  3 
45   2/20/2014  OBS  1 
45   2/25/2014  OBS  2 
45   2/30/2014  OBS  3 
45   2/32/2014  OBS  4 

我已經開始這樣的事情,但是無法完成它:

SELECT PATIENT_ID, ADMIT_DATE, LOCATION, 
CASE WHEN MIN(ADMIT_DATE)-MAX(ADMIT_DATE)<48 THEN 1 ELSE 0 AS FLAG 
FROM MYTABLE 
GROUP BY PATIENT_ID, ADMIT_DATE, LOCATION 

有人可以幫忙嗎?

+0

是什麼 「但無法完成它」 是什麼意思? – 2014-11-02 04:46:25

+0

沒有2014年2月31日和32日:-) – gotqn 2014-11-02 09:24:59

回答

1

你可以做到這一點很容易使用LAGDATEDIFFROWNUMBER功能。 LAG函數可幫助您獲得以前的ADMIT_DATE值。然後,您可以使用DATEDIFF函數計算以小時計的差異。最後,使用ROWNUMBER你可以簡單地排列你的結果。

這個充滿工作示例:

SET NOCOUNT ON 
GO 

    DECLARE @DataSource TABLE 
    (
     [ATIENT_ID] TINYINT 
     ,[ADMIT_DATE] DATE 
     ,[LOCATION] VARCHAR(3) 
    ) 

    INSERT INTO @DataSource ([ATIENT_ID], [ADMIT_DATE], [LOCATION]) 
    VALUES (33, '1-10-2014', 'ER') 
      ,(33, '1-11-2014', 'ER') 
      ,(33, '1-15-2014', 'ER') 
      ,(33, '1-17-2014', 'ER') 
      ,(45, '2-15-2014', 'OBS') 
      ,(45, '2-16-2014', 'OBS') 
      ,(45, '2-20-2014', 'OBS') 
      ,(45, '2-25-2014', 'OBS') 
      ,(45, '2-27-2014', 'OBS') 

    ;WITH DataSource ([ATIENT_ID], [ADMIT_DATE], [LOCATION], [DIFF_IN_HOURS]) AS 
    (
     SELECT [ATIENT_ID] 
       ,[ADMIT_DATE] 
       ,[LOCATION] 
       ,DATEDIFF(
          HOUR 
          ,LAG([ADMIT_DATE], 1, NULL) OVER (PARTITION BY [ATIENT_ID], [LOCATION] ORDER BY [ADMIT_DATE] ASC) 
          ,[ADMIT_DATE] 
         ) 
     FROM @DataSource 
    ) 
    SELECT [ATIENT_ID] 
      ,[ADMIT_DATE] 
      ,[LOCATION] 
      ,ROW_NUMBER() OVER (PARTITION BY [ATIENT_ID], [LOCATION] ORDER BY [ADMIT_DATE] ASC) 
    FROM DataSource 
    WHERE [DIFF_IN_HOURS] >= 48 
     OR [DIFF_IN_HOURS] IS NULL -- these are first records 

SET NOCOUNT OFF 
GO 

enter image description here

注意,我有固定的樣本數據,因爲它是錯誤的。


這是一個沒有LAG功能的替代解決方案:

;WITH TempDataSource ([ATIENT_ID], [ADMIT_DATE], [LOCATION], [Rank]) AS 
(
    SELECT [ATIENT_ID] 
      ,[ADMIT_DATE] 
      ,[LOCATION] 
      ,ROW_NUMBER() OVER (PARTITION BY [ATIENT_ID], [LOCATION] ORDER BY [ADMIT_DATE] ASC) 
    FROM @DataSource  
), 
DataSource ([ATIENT_ID], [ADMIT_DATE], [LOCATION], [DIFF_IN_HOURS]) AS 
(
SELECT DS1.[ATIENT_ID] 
     ,DS1.[ADMIT_DATE] 
     ,DS1.[LOCATION] 
     ,DATEDIFF(HOUR, DS2.[ADMIT_DATE], DS1.[ADMIT_DATE]) 
FROM TempDataSource DS1 
LEFT JOIN TempDataSource DS2 
    ON DS1.[Rank] - 1 = DS2.[Rank] 
    AND DS1.[ATIENT_ID] = DS2.[ATIENT_ID] 
    AND DS1.[LOCATION] = DS2.[LOCATION] 
) 
SELECT [ATIENT_ID] 
     ,[ADMIT_DATE] 
     ,[LOCATION] 
     ,ROW_NUMBER() OVER (PARTITION BY [ATIENT_ID], [LOCATION] ORDER BY [ADMIT_DATE] ASC) 
FROM DataSource 
WHERE [DIFF_IN_HOURS] >= 48 
    OR [DIFF_IN_HOURS] IS NULL -- these are first records 
+0

感謝您的詳細解決方案,但我有一個問題。 LAG函數只適用於SQL Server 2012,但我正在使用SQL Server 2008.是否有另一個功能或不同的解決方案,我可以使用?謝謝 – moe 2014-11-02 15:05:40

+0

是的,它僅適用於「SQL Server 2012」和「SQL Server 2014」。 workarround很簡單 - 使用'OVER(PARTITION BY [ATIENT_ID],[LOCATION] ORDER BY [ADMIT_DATE] ASC)''使用'ROW_NUMBER()'函數創建一個臨時的排名結果集,然後使用'SELECT'和' SELF JOIN'來獲取之前的記錄。如果有什麼不清楚,請告訴我。 – gotqn 2014-11-02 16:18:26

+0

@moe檢查編輯。 – gotqn 2014-11-02 16:26:04

0
SELECT Patient_id,Admit_date, Location, 
CASE WHEN DATEDIFF (HH , min(admit_date) , max(admit_date)) < 48 THEN count(flag)+1 ELSE 0 End As Flag 
FROM tbl_Patient 
GROUP BY PATIENT_ID, ADMIT_DATE, LOCATION 
相關問題