老派方法,但我会创建第二个表:
CREATE TABLE SplitTimes (
SplitStart time not null,
SplitEnd time not null,
primary key (SplitStart, SplitEnd)
)
并填充它:
INSERT INTO SplitTimes (SplitStart, SplitEnd) VALUES
('0:00', '0:30'),
('0:30', '1:00'),
('1:00', '1:30'),
('1:30', '2:00'),
('2:00', '2:30'),
('2:30', '3:00'),
('3:00', '3:30'),
('3:30', '4:00'),
('4:00', '4:30'),
('4:30', '5:00'),
('5:00', '5:30'),
('5:30', '6:00'),
('6:00', '6:30'),
('6:30', '7:00'),
('7:00', '7:30'),
('7:30', '8:00'),
('8:00', '8:30'),
('8:30', '9:00'),
('9:00', '9:30'),
('9:30', '10:00'),
('10:00', '10:30'),
('10:30', '11:00'),
('11:00', '11:30'),
('11:30', '12:00'),
('12:00', '12:30'),
('12:30', '13:00'),
('13:00', '13:30'),
('13:30', '14:00'),
('14:00', '14:30'),
('14:30', '15:00'),
('15:00', '15:30'),
('15:30', '16:00'),
('16:00', '16:30'),
('16:30', '17:00'),
('17:00', '17:30'),
('17:30', '18:00'),
('18:00', '18:30'),
('18:30', '19:00'),
('19:00', '19:30'),
('19:30', '20:00'),
('20:00', '20:30'),
('20:30', '21:00'),
('21:00', '21:30'),
('21:30', '22:00'),
('22:00', '22:30'),
('22:30', '23:00'),
('23:00', '23:30'),
('23:30', '23:59:59.9999999');
现在我可以运行这个了:
SELECT e.UserID
,case when e.StatusStart >= t.SplitStart then e.StatusStart else t.SplitStart end as SplitStatusStart
,case when e.StatusEnd <= t.SplitEnd then e.StatusEnd else t.SplitEnd end as SplitStatusEnd
,e.StatusKey
,datediff(second, case when e.StatusStart >= t.SplitStart then e.StatusStart else t.SplitStart end,
case when e.StatusEnd <= t.SplitEnd then e.StatusEnd else t.SplitEnd end) SplitStatusDuration
FROM EntryTable e
INNER JOIN SplitTimes t
ON e.StatusStart <= t.SplitEnd
AND e.StatusEnd >= t.SplitStart
它可以使用日期时间而不是时间,并且可以在午夜工作。从日期中删除时间并重新添加另一个只是额外的摆弄。
这具有不是递归 CTE 的优点,它可能在大表上表现更好。