简体   繁体   中英

How to find the difference between dates within the same column using SQL?

I am trying to solve the following challenge:

1) If a patient visits the ER within 48 hours, I want to flag that as 1 .

2) If the same patient visits the ER again after 48 hours, I want to flag that as 2 .

3) Each subsequent visit must be flagged as 3 , 4 , 5 etcetera after the first 48 hours.

Here is what my table looks like:

  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

And here is what the desired result should look like:

 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

I have started something like this but could not complete it:

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

Can someone please help?

You can achieve this easy using LAG , DATEDIFF and ROWNUMBER functions. The LAG function helps you to get the previous ADMIT_DATE value. Then you can calculate the difference in hours using the DATEDIFF function. Finally, using ROWNUMBER you can simple rank your results.

This is full working example:

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

在此处输入图片说明

Note, I have fixed your sample data as it was wrong.


This is alternative solution without LAG function:

;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

you can use DATEDIFF() available in sql-server like

SELECT DATEDIFF(hour,startDate,endDate) AS 'Duration'

You can visit http://msdn.microsoft.com/en-IN/library/ms189794.aspx

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM