如何计算在SQL-server-2008-r2中按小时和日期分组的打开记录

时间:2013-01-29 13:59:02

标签: sql sql-server sql-server-2008-r2

我在Microsoft SQL Server r2中有医院患者入院数据,如下所示:

PatientID, AdmitDate,        DischargeDate
Jones.     1-jan-13 01:37.   1-jan-13 17:45
Smith      1-jan-13 02:12.   2-jan-13 02:14
Brooks.    4-jan-13 13:54.   5-jan-13 06:14

我想计算一天一小时的医院病人数量(即

1-jan-13 00:00. 0
1-jan-13 01:00. 0
1-jan-13 02:00. 1
1-jan-13 03:00. 2

我需要包括结果中没有患者入院的时间。

我无法创建表格,因此制作一个列出所有时间和日期的参考表已经出来了。

有什么建议吗?

4 个答案:

答案 0 :(得分:1)

这是一种(丑陋的)方式:

;WITH DayHours AS
(
    SELECT 0 DayHour
    UNION ALL
    SELECT DayHour+1
    FROM DayHours
    WHERE DayHour+1 <= 23
)
SELECT B.AdmitDate, A.DayHour, COUNT(DISTINCT PatientID) Patients
FROM DayHours A
CROSS JOIN (SELECT DISTINCT CONVERT(DATE,AdmitDate) AdmitDate
            FROM YourTable) B
LEFT JOIN YourTable C
    ON B.AdmitDate = CONVERT(DATE,C.AdmitDate)
    AND A.DayHour = DATEPART(HOUR,C.AdmitDate)
GROUP BY B.AdmitDate, A.DayHour

答案 1 :(得分:1)

要解决此问题,您需要一个日期时间列表。以下内容从允许日期交叉连接到24小时的表格中获取。 24小时表从information_schema.columns计算 - 这是在SQL Server中获取小数字序列的技巧。

其余的只是这张桌子和小时之间的连接。该版本在一小时内对患者进行计数,因此例如在同一时间内入院和出院的人不计算在内。一般来说,有人在被录取后的下一个小时才被计算在内:

with dh as (
     select DATEADD(hour, seqnum - 1, thedatehour ) as DateHour
     from (select distinct cast(cast(AdmitDate as DATE) as datetime) as thedatehour
           from Admission a
          ) a cross join
          (select ROW_NUMBER() over (order by (select NULL)) as seqnum
           from INFORMATION_SCHEMA.COLUMNS
          ) hours
          where hours <= 24
    )
select dh.DateHour, COUNT(*) as NumPatients
from dh join
     Admissions a
     on dh.DateHour between a.AdmitDate and a.DischargeDate
group by dh.DateHour
order by 1

这也假设每天都有入学许可。这似乎是一个合理的假设。如果没有,日历表将是一个很大的帮助。

答案 2 :(得分:1)

这有点乱,包含一个临时表,其中包含您提供的测试数据

    CREATE TABLE #HospitalPatientData (PatientId NVARCHAR(MAX), AdmitDate DATETIME, DischargeDate DATETIME)
INSERT INTO #HospitalPatientData
SELECT 'Jones.',     '1-jan-13 01:37:00.000',   '1-jan-13 17:45:00.000' UNION
SELECT 'Smith',      '1-jan-13 02:12:00.000',   '2-jan-13 02:14:00.000' UNION
SELECT 'Brooks.',    '4-jan-13 13:54:00.000',  '5-jan-13 06:14:00.000'

;WITH DayHours AS
(
    SELECT 0 DayHour
    UNION ALL
    SELECT DayHour+1
    FROM DayHours
    WHERE DayHour+1 <= 23
),
HospitalPatientData AS
(
SELECT CONVERT(nvarchar(max),AdmitDate,103) as AdmitDate ,DATEPART(hour,(AdmitDate)) as     AdmitHour, COUNT(PatientID) as CountOfPatients
FROM #HospitalPatientData
GROUP BY CONVERT(nvarchar(max),AdmitDate,103), DATEPART(hour,(AdmitDate))
),
Results AS
(
SELECT MAX(h.AdmitDate) as Date, d.DayHour
FROM HospitalPatientData h
INNER JOIN DayHours d ON d.DayHour=d.DayHour
GROUP BY AdmitDate, CountOfPatients, DayHour
)

SELECT r.*, COUNT(h.PatientId) as CountOfPatients
FROM Results r
LEFT JOIN #HospitalPatientData h ON CONVERT(nvarchar(max),AdmitDate,103)=r.Date AND     DATEPART(HOUR,h.AdmitDate)=r.DayHour
GROUP BY r.Date, r.DayHour
ORDER BY r.Date, r.DayHour

DROP TABLE #HospitalPatientData

答案 3 :(得分:0)

这可能会让你开始:

BEGIN TRAN

DECLARE @pt TABLE
    (
      PatientID VARCHAR(10)
    , AdmitDate DATETIME
    , DischargeDate DATETIME
    )

INSERT  INTO @pt
        ( PatientID, AdmitDate, DischargeDate )
VALUES  ( 'Jones', '1-jan-13 01:37', '1-jan-13 17:45' ),
        ( 'Smith', '1-jan-13 02:12', '2-jan-13 02:14' )
,       ( 'Brooks', '4-jan-13 13:54', '5-jan-13 06:14' )



DECLARE @StartDate DATETIME = '20130101'
    , @FutureDays INT = 7


;
WITH    dy
          AS ( SELECT TOP (@FutureDays)
                        ROW_NUMBER() OVER ( ORDER BY name ) dy
               FROM     sys.columns c
             ) ,
        hr
          AS ( SELECT TOP 24
                        ROW_NUMBER() OVER ( ORDER BY name ) hr
               FROM     sys.columns c
             )
    SELECT  refDate, COUNT(p.PatientID) AS PtCount
    FROM    ( SELECT    DATEADD(HOUR, hr.hr - 1,
                                DATEADD(DAY, dy.dy - 1, @StartDate)) AS refDate
              FROM      dy
                        CROSS JOIN hr
            ) ref
    LEFT JOIN @pt p ON ref.refDate BETWEEN p.AdmitDate AND p.DischargeDate        
    GROUP BY refDate

ORDER BY refDate

ROLLBACK