如何使用SQL查找同一列中的日期之间的差异?

时间:2014-11-02 04:44:13

标签: sql sql-server tsql

我正在尝试解决以下挑战:

1)如果患者在48小时内访问ER,我想将其标记为1

2)如果同一患者在48小时后再次访问ER,我想将其标记为2

3)在最初的48小时后,每次后续访问都必须标记为345等。

以下是我的表格:

  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

有人可以帮忙吗?

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

您可以使用sql-server中的DATEDIFF(),如

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

您可以访问http://msdn.microsoft.com/en-IN/library/ms189794.aspx

答案 2 :(得分: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