首先你需要一個數字表,從0讓你的時間 - 23,它可以很容易的飛行與表值構造函數創建:
SELECT N
FROM (VALUES
(0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),
(13),(14),(15),(16),(17),(18),(19),(20),(21),(22),(23)
) n (N);
然後你就可以加入這個以自己的原始數據將行分成所需的數量。然後你只需要一個CASE表達式應用正確的邏輯來計算分:
WITH Numbers (Number) AS
( SELECT N
FROM (VALUES
(0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),
(13),(14),(15),(16),(17),(18),(19),(20),(21),(22),(23)
) n (N)
), SampleData (tid, StartDate, EndDate) AS
( SELECT tid, CONVERT(DATETIME2, StartDate), CONVERT(DATETIME2, EndDate)
FROM (VALUES
(1, '2016-12-26 12:30', '2016-12-26 15:30'),
(2, '2016-12-26 13:15', '2016-12-26 15:15')
) d (tid, StartDate, EndDate)
)
SELECT d.tid,
[Hour] = n.Number,
Minutes_in = CASE
-- SPECIAL CASE: START HOUR = END HOUR
WHEN DATEPART(HOUR, d.StartDate) = DATEPART(HOUR, d.EndDate)
THEN DATEDIFF(MINUTE, d.StartDate, d.EndDate)
-- FULL HOURS IN BETWEEN START AND END
WHEN n.Number > DATEPART(HOUR, d.StartDate)
AND n.Number < DATEPART(HOUR, d.EndDate) THEN 60
-- START HOUR
WHEN n.Number = DATEPART(HOUR, d.StartDate)
THEN 60 - DATEPART(MINUTE, d.StartDate)
-- END HOUR
WHEN n.Number = DATEPART(HOUR, d.EndDate)
THEN DATEPART(MINUTE, d.EndDate)
END
FROM SampleData d
INNER JOIN Numbers n
ON n.Number >= DATEPART(HOUR, d.StartDate)
AND n.Number <= DATEPART(HOUR, d.EndDate);
附錄
如果你需要跨越數日,那麼你可以稍稍改變邏輯,產生一個更大的集數字覆蓋更多的時間差,然後,而不是加入當天的小時,加入的人數從一開始的日期時間到結束日期時間的時間差:
SELECT *
FROM SampleData d
INNER JOIN Numbers n
ON n.Number <= DATEDIFF(HOUR, d.StartDate, d.EndDate)
這意味着地方該範圍跨越幾天,然後沒有問題,小時只是不斷增加。例如
WITH Numbers (Number) AS
( SELECT ROW_NUMBER() OVER(ORDER BY N1.N) - 1
FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N1(N)
CROSS JOIN (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N2 (N)
CROSS JOIN (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N3 (N)
CROSS JOIN (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N4 (N)
), SampleData (tid, StartDate, EndDate) AS
( SELECT tid, CONVERT(DATETIME2, StartDate), CONVERT(DATETIME2, EndDate)
FROM (VALUES
(1, '2016-12-26 12:30', '2016-12-26 15:30'),
(2, '2016-12-26 13:15', '2016-12-26 15:15'),
(3, '2016-12-26 13:15', '2016-12-27 15:15')
) d (tid, StartDate, EndDate)
)
SELECT d.tid,
[Date] = CONVERT(DATE, d.StartDate),
[Hour] = CONVERT(TIME(0), DATEADD(HOUR, DATEPART(HOUR, d.StartDate) + n.Number, 0)),
Minutes_in = CASE
-- SPECIAL CASE: START HOUR = END HOUR
WHEN DATEPART(HOUR, d.StartDate) = DATEPART(HOUR, d.EndDate)
AND DATEDIFF(DAY, d.StartDate, d.EndDate) = 0
THEN DATEDIFF(MINUTE, d.StartDate, d.EndDate)
-- START HOUR
WHEN n.Number = 0
THEN 60 - DATEPART(MINUTE, d.StartDate)
-- END HOUR
WHEN n.Number = DATEDIFF(HOUR, d.StartDate, d.EndDate)
THEN DATEPART(MINUTE, d.EndDate)
-- FULL HOURS IN BETWEEN START AND END
ELSE 60
END
FROM SampleData d
INNER JOIN Numbers n
ON n.Number <= DATEDIFF(HOUR, d.StartDate, d.EndDate)
ORDER BY d.tid, n.Number;
如何分鐘隔離 – TheGameiswar
我CURI - 爲什麼你需要這個結果?這只是一個更大的目標嗎?感覺這有可能是一個[XY問題](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)。 – 3N1GM4
每個tid都是用戶登錄/註銷時間。我需要每小時登錄分鐘。因此,如果三名用戶在12:00至13:00之間登錄30分鐘,這將導致90分鐘的登錄時間在12小時內。 – phicon