SQL显示每天的每一小时

时间:2018-11-02 16:41:49

标签: sql tsql

我编写了以下代码,以分解我的数据,该数据显示每天的患者出入情况,每天按小时进行一次患者普查。

该代码有效,但是对于每个日期,它不会为0-23的每个小时增加一个小时,而是为0添加第二行,因此它每天分成25行而不是24行。我很确定问题在下面的“交叉应用”中,但是我提供了其余代码供您参考。

非常感谢您能提供的任何帮助。另外,如果您对如何在此处发布代码有任何建议,并使代码看起来更正常,请告诉我。谢谢!

--Create my temporary table 
SELECT *
INTO #Temporary
FROM dbo.Census
WHERE YEAR(startdatetime) >= 2018
ORDER BY
    startdatetime
    ,pt_id

--Use the Cross Apply to split out every day into every hour 
SELECT
    Date = CAST(D AS DATE)
    ,Hour = DATEPART(HOUR, D)
    ,pt_id
    ,cendate
    ,locationid
    ,[room-bed]
    ,startdatetime
    ,enddatetime
    ,minutes
    ,DayOfWeek
    ,WeekInt
    ,MyStartMinutes = 0
    ,MyEndMinutes = 0
INTO #Temporary2
FROM #Temporary A
CROSS APPLY
(
    SELECT TOP ( ABS(DATEDIFF(HOUR, A.startdatetime, A.enddatetime) + 1))
        D = DATEADD(HOUR, -1 + ROW_NUMBER() OVER ( ORDER BY ( SELECT NULL )), A.startdatetime)
    FROM master..spt_values n1
        ,master..spt_values n2
) B

--Update values for MyStartMinutes and MyEndMinutes 
UPDATE #Temporary2
SET MyStartMinutes = CASE WHEN ( DATEPART(HOUR, startdatetime) = Hour )
                              THEN DATEPART(mi, enddatetime)
                         ELSE 0 END

UPDATE #Temporary2
SET MyEndMinutes = CASE WHEN ( DATEPART(HOUR, enddatetime) = Hour )
                            AND DATEDIFF(DAY, enddatetime, cendate) = 0
                            THEN DATEPART(mi, enddatetime)
                       ELSE 0 END

--Update values of startdatetime and enddatetime 
UPDATE #Temporary2
SET startdatetime = DATEADD(HOUR, Hour, DATEADD(MINUTE, MyStartMinutes, CAST(CAST(startdatetime AS DATE) AS DATETIME)))

UPDATE #Temporary2
SET enddatetime = CASE WHEN ( Hour < 23 )
                           THEN ( DATEADD(HOUR, Hour + 1, DATEADD(MINUTE, MyEndMinutes, CAST(CAST(startdatetime AS DATE) AS DATETIME))))
                      WHEN Hour = 23
                          THEN ( DATEADD(HOUR, 0, DATEADD(MINUTE, MyEndMinutes, CAST(CAST(enddatetime AS DATE) AS DATETIME))))
                      ELSE '' END

--Update Value of Minutes 
UPDATE #Temporary2
SET Minutes = DATEDIFF(mi, startdatetime, enddatetime)

SELECT * 
FROM #Temporary2 
ORDER BY minutes DESC

以下是dbo.Census的示例数据:

org pt_id cendate   location bed    startdate      enddate           minutes DOW 
A   5     1/8/2018    7E     50    1/8/2018 8:00    1/9/2018 0:00    960     Mon 
A   5     1/9/2018    7E     50    1/9/2018 0:00    1/10/2018 0:00   1440    Tue 
A   5     1/10/2018   7E     50    1/10/2018 0:00   1/11/2018 0:00   1440    Wed 
A   5     1/11/2018   7E     50    1/11/2018 0:00   1/11/2018 14:00  840     Thu 
A   1     10/17/2016  ED     10    10/17/2016 1:05  10/17/2016 10:21 556     Mon 
A   2     5/10/2017   4L     20    5/10/2017 15:09  5/11/2017 0:00   531     Wed 
A   3     5/14/2017   4L     30    5/14/2017 0:00   5/14/2017 8:12   492     Sun 
A   4     6/3/2017    5C     40    6/3/2017 0:00    6/4/2017 0:00    1440    Sat 

1 个答案:

答案 0 :(得分:1)

我认为您的CROSS APPLY是罪魁祸首是正确的。在根据我自己的示例数据测试代码之后,我发现如果dbo.Census中有单独的记录,它们的开始日期和结束日期之间有重叠的天数,则这些日期和时间将被重复,具体取决于多少条记录和多少条记录他们分享的日子。

所以我要做的是将dbo.Census中的PK添加到CROSS APPLY中,然后在子查询中使用该id列将结果仅过滤到那些ID匹配的结果。这是我更改的代码部分:

SELECT
    Date = CAST(D AS DATE)
    ,Hour = DATEPART(HOUR, D)
    ,A.pt_id
    ,cendate
    ,locationid
    ,[room-bed]
    ,startdatetime
    ,enddatetime
    ,minutes
    ,DayOfWeek
    ,WeekInt
    ,MyStartMinutes = 0
    ,MyEndMinutes = 0
INTO #Temporary2
FROM #Temporary A
CROSS APPLY
(
    SELECT TOP ( ABS(DATEDIFF(HOUR, A.startdatetime, A.enddatetime) + 1))
        D = DATEADD(HOUR, -1 + ROW_NUMBER() OVER ( ORDER BY ( SELECT NULL )), A.startdatetime)
        ,A.pt_id
    FROM master..spt_values n1
        ,master..spt_values n2
) B
WHERE A.pt_id = B.pt_id

我假设pt_iddbo.Census的主键。如果不是这种情况,您只需将pt_id的PK替换为dbo.Census