SQL Server и выделить время в часах - PullRequest
0 голосов
/ 15 ноября 2018

Справочная информация:

Машины скорой помощи и пожарные машины имеют время отправки, когда произошла чрезвычайная ситуация, и четкое время, когда чрезвычайная ситуация была объявлена.

Например: аварийная ситуация (EventID = fire0001) возникает в 10:45:00 и заканчивается в 11:30:00.

Другое экстренное событие (EventID = fire0002) начинается в 11:50:00 и заканчивается в 13: 10: 00

Вопрос:

Я хотел бы проанализировать количество времени от начала до конца и поместить его в части часа, когда это произойдет. Например; fire0001 начинается в 10:45 и заканчивается в 11:30.

Я бы хотел, чтобы результаты показывали 15 минут в 10-часовой части и 30 минут в 11-часовой части.

eventID    HourOfDay    Minutes forThisHourPart
------------------------------------------------    
fire0001       10              15
fire0001       11              30

Эта информация полезна для планирования скорой помощи, чтобы определить использование для каждого часа дня.

Как рассчитать количество времени, проведенного за час, с учетом времени начала и окончания?

CREATE TABLE tempFireEvents
(
    EventID VARCHAR(8) NOT NULL,
    StartDateTime DATETIME NOT NULL,
    EndDateTime DATETIME NOT NULL
)

INSERT INTO tempFireEvents
VALUES
    ('fire0001', 'november 1, 2018 10:45:00', 'november 1, 2108 11:30:00'),
    ('fire0002', 'november 1, 2018 11:50:00', 'november 1, 2018 13:10:00'),
    ('fire0003', 'november 1, 2018 13:20:00', 'november 1, 2108 14:20:00'),
    ('fire0004', 'november 1, 2018 15:25:00', 'november 1, 2018 16:05:00'),
    ('fire0005', 'november 1, 2018 16:20:00', 'november 1, 2018 16:50:00');


--SELECT EventID, StartDateTime, EndDateTime FROM tempFireEvents;

Ответы [ 3 ]

0 голосов
/ 15 ноября 2018

может быть что-то вроде этого

select EventID,
       datepart(hour, StartDateTime) AS StartHour,
       datediff(minute, StartDateTime, dateadd(hour, datediff(hour, 0, StartDateTime) + 1, 0)) AS StartMinutes,
       datepart(hour, EndDateTime) AS EndHour,
       datediff(minute, EndDateTime, dateadd(hour, datediff(hour, 0, EndDateTime) + 1, 0)) AS EndMinutes
from   tempFireEvents

это возвращает

EventID StartHour   StartMinutes    EndHour EndMinutes  
------- ---------   ------------    ------- ----------  
fire0001    10          15             11       30  
fire0002    11          10             13       50  
fire0003    13          40             14       40  
fire0004    15          35             16       55  
fire0005    16          40             16       10  
0 голосов
/ 15 ноября 2018

Я верю, что это то, что вы хотите:

DECLARE @tempFireEvents TABLE
(
    EventID VARCHAR(8) NOT NULL,
    StartDateTime DATETIME NOT NULL,
    EndDateTime DATETIME NOT NULL
)

INSERT INTO @tempFireEvents
VALUES
    ('fire0001', 'november 1, 2018 10:45:00', 'november 1, 2108 11:30:00'),
    ('fire0002', 'november 1, 2018 11:50:00', 'november 1, 2018 13:10:00'),
    ('fire0003', 'november 1, 2018 13:20:00', 'november 1, 2108 14:20:00'),
    ('fire0004', 'november 1, 2018 15:25:00', 'november 1, 2018 16:05:00'),
    ('fire0005', 'november 1, 2018 16:20:00', 'november 1, 2018 16:50:00')

;WITH AllHours AS
(
    SELECT 1 AS hourInt
    UNION ALL
    SELECT hourInt+1
    FROM AllHours
    WHERE hourInt<23
), Combined AS
    (
        SELECT T.EventID,
               H.hourInt,
               CASE WHEN DATEPART(HOUR,T.StartDateTime)=H.hourInt THEN 1 ELSE 0 END AS isStart,
               CASE WHEN DATEPART(HOUR,T.EndDateTime)=H.hourInt THEN 1 ELSE 0 END AS isEnd,
               T.StartDateTime,
               T.EndDateTime
        FROM @tempFireEvents T
        JOIN AllHours H ON H.hourInt BETWEEN DATEPART(HOUR,T.StartDateTime) AND DATEPART(HOUR,T.EndDateTime)
    )

--SELECT * FROM Combined

SELECT EventID,
       hourInt,
       CASE WHEN isStart=1 AND isEnd=0 THEN 60-DATEPART(MINUTE,StartDateTime)
            WHEN isStart=0 AND isEnd=1 THEN DATEPART(MINUTE,EndDateTime)
            WHEN isStart=1 AND isEnd=1 THEN DATEPART(MINUTE,EndDateTime)-DATEPART(MINUTE,StartDateTime)
            ELSE 60
       END AS minutesForHour
FROM Combined

Выход:

EventID     hourInt     minutesForHour
fire0001    10          15
fire0001    11          30
fire0002    11          10
fire0002    12          60
fire0002    13          10
fire0003    13          40
fire0003    14          20
fire0004    15          35
fire0004    16          5
fire0005    16          30

Как уже упоминалось в комментариях, способ хранения EventID далек от оптимального. Лучший подход - назначить «тип» каждому событию, например:

DECLARE @EventType TABLE 
(
    Id INT,
    EventType NVARCHAR(50)
)

INSERT INTO @EventType
VALUES
    (1,'Fire'),
    (2,'Public Awareness'),
    (3,'Cat in a Tree'),
    (4,'Motor Vehicle Accident')

DECLARE @tempFireEvents TABLE
(
    EventID INT IDENTITY (1,1) NOT NULL,
    EventTypeID INT NOT NULL,
    StartDateTime DATETIME NOT NULL,
    EndDateTime DATETIME NOT NULL
)

INSERT INTO @tempFireEvents (EventTypeID,StartDateTime,EndDateTime)
VALUES
    (1, 'november 1, 2018 10:45:00', 'november 1, 2108 11:30:00'),
    (2, 'november 1, 2018 11:50:00', 'november 1, 2018 13:10:00'),
    (4, 'november 1, 2018 13:20:00', 'november 1, 2108 14:20:00'),
    (1, 'november 1, 2018 15:25:00', 'november 1, 2018 16:05:00'),
    (3, 'november 1, 2018 16:20:00', 'november 1, 2018 16:50:00')

;WITH AllHours AS
(
    SELECT 1 AS hourInt
    UNION ALL
    SELECT hourInt+1
    FROM AllHours
    WHERE hourInt<23
), Combined AS
    (
        SELECT T.EventID,
               T.EventTypeID,
               H.hourInt,
               CASE WHEN DATEPART(HOUR,T.StartDateTime)=H.hourInt THEN 1 ELSE 0 END AS isStart,
               CASE WHEN DATEPART(HOUR,T.EndDateTime)=H.hourInt THEN 1 ELSE 0 END AS isEnd,
               T.StartDateTime,
               T.EndDateTime
        FROM @tempFireEvents T
        JOIN AllHours H ON H.hourInt BETWEEN DATEPART(HOUR,T.StartDateTime) AND DATEPART(HOUR,T.EndDateTime)
    )

--SELECT * FROM Combined

SELECT C.EventID,
       T.EventType,
       C.hourInt,
       CASE WHEN C.isStart=1 AND C.isEnd=0 THEN 60-DATEPART(MINUTE,C.StartDateTime)
            WHEN C.isStart=0 AND C.isEnd=1 THEN DATEPART(MINUTE,C.EndDateTime)
            WHEN C.isStart=1 AND C.isEnd=1 THEN DATEPART(MINUTE,C.EndDateTime)-DATEPART(MINUTE,C.StartDateTime)
            ELSE 60
       END AS minutesForHour
FROM Combined C
Join @EventType t ON C.EventTypeID=T.Id
ORDER BY C.EventID, C.hourInt

Выход:

EventID EventType               hourInt minutesForHour
1       Fire                    10      15
1       Fire                    11      30
2       Public Awareness        11      10
2       Public Awareness        12      60
2       Public Awareness        13      10
3       Motor Vehicle Accident  13      40
3       Motor Vehicle Accident  14      20
4       Fire                    15      35
4       Fire                    16      5
5       Cat in a Tree           16      30
0 голосов
/ 15 ноября 2018
SELECT EventID,
       DATEPART(hour, StartDateTime) AS HourOfDay,
       DATEDIFF(minute, StartDateTime, DATEADD(hour, DATEDIFF(hour, 0, StartDateTime) + 1, 0)) AS MinutesForThisHourPart
FROM tempFireEvents
UNION ALL
SELECT EventID,
       DATEPART(hour, EndDateTime) AS HourOfDay,
       DATEDIFF(minute, EndDateTime, DATEADD(hour, DATEDIFF(hour, 0, EndDateTime) + 1, 0)) AS MinutesForThisHourPart
FROM tempFireEvents
ORDER BY 1

Результат

EventID  HourOfDay   MinutesForThisHourPart
-------- ----------- ----------------------
fire0001 10          15
fire0001 11          30
fire0002 11          10
fire0002 13          50
fire0003 13          40
fire0003 14          40
fire0004 15          35
fire0004 16          55
fire0005 16          10
fire0005 16          40
...