Sql server 从其他日期时间范围中减去日期时间范围(T-SQL)
我需要一些帮助来创建SQL查询。至少有一点关于如何做到这一点的提示。 我有一个带有datetime范围的表时间表,还有一个带有datetime范围的表UnavailableTimes。从这个我想要的可用时间,从时间表中减去不可用的时间 T-SQL(测试数据)Sql server 从其他日期时间范围中减去日期时间范围(T-SQL),sql-server,tsql,datetime,range,subtraction,Sql Server,Tsql,Datetime,Range,Subtraction,我需要一些帮助来创建SQL查询。至少有一点关于如何做到这一点的提示。 我有一个带有datetime范围的表时间表,还有一个带有datetime范围的表UnavailableTimes。从这个我想要的可用时间,从时间表中减去不可用的时间 T-SQL(测试数据) CREATE TABLE Schedule ( ID INT, StartTime DATETIME, EndTime DATETIME ) CREATE TABLE UnavailableTimes (
CREATE TABLE Schedule (
ID INT,
StartTime DATETIME,
EndTime DATETIME
)
CREATE TABLE UnavailableTimes (
ID INT,
StartTime DATETIME,
EndTime DATETIME
)
CREATE TABLE AvailableTimes (
ID INT,
StartTime DATETIME,
EndTime DATETIME
)
INSERT INTO Schedule (ID, StartTime, EndTime)
VALUES
(2, '2018-02-27 08:00', '2018-02-27 12:00'),
(2, '2018-02-27 13:00', '2018-02-27 17:00')
INSERT INTO UnavailableTimes (ID, StartTime, EndTime)
VALUES
(2, '2018-02-27 07:30', '2018-02-27 08:30'),
(2, '2018-02-27 08:00', '2018-02-27 09:30'),
(2, '2018-02-27 13:30', '2018-02-27 14:00'),
(2, '2018-02-27 16:00', '2018-02-27 18:00')
ID StartTime EndTime
2 2018-02-27 08:00 2018-02-27 12:00
2 2018-02-27 13:00 2018-02-27 17:00
ID StartTime EndTime
2 2018-02-27 07:30 2018-02-27 08:30
2 2018-02-27 08:00 2018-02-27 09:30
2 2018-02-27 13:30 2018-02-27 14:00
2 2018-02-27 16:00 2018-02-27 18:00
ID StartTime EndTime
2 2018-02-27 09:30 2018-02-27 12:00
2 2018-02-27 13:00 2018-02-27 13:30
2 2018-02-27 14:00 2018-02-27 16:00
时间表
CREATE TABLE Schedule (
ID INT,
StartTime DATETIME,
EndTime DATETIME
)
CREATE TABLE UnavailableTimes (
ID INT,
StartTime DATETIME,
EndTime DATETIME
)
CREATE TABLE AvailableTimes (
ID INT,
StartTime DATETIME,
EndTime DATETIME
)
INSERT INTO Schedule (ID, StartTime, EndTime)
VALUES
(2, '2018-02-27 08:00', '2018-02-27 12:00'),
(2, '2018-02-27 13:00', '2018-02-27 17:00')
INSERT INTO UnavailableTimes (ID, StartTime, EndTime)
VALUES
(2, '2018-02-27 07:30', '2018-02-27 08:30'),
(2, '2018-02-27 08:00', '2018-02-27 09:30'),
(2, '2018-02-27 13:30', '2018-02-27 14:00'),
(2, '2018-02-27 16:00', '2018-02-27 18:00')
ID StartTime EndTime
2 2018-02-27 08:00 2018-02-27 12:00
2 2018-02-27 13:00 2018-02-27 17:00
ID StartTime EndTime
2 2018-02-27 07:30 2018-02-27 08:30
2 2018-02-27 08:00 2018-02-27 09:30
2 2018-02-27 13:30 2018-02-27 14:00
2 2018-02-27 16:00 2018-02-27 18:00
ID StartTime EndTime
2 2018-02-27 09:30 2018-02-27 12:00
2 2018-02-27 13:00 2018-02-27 13:30
2 2018-02-27 14:00 2018-02-27 16:00
不可用时间
CREATE TABLE Schedule (
ID INT,
StartTime DATETIME,
EndTime DATETIME
)
CREATE TABLE UnavailableTimes (
ID INT,
StartTime DATETIME,
EndTime DATETIME
)
CREATE TABLE AvailableTimes (
ID INT,
StartTime DATETIME,
EndTime DATETIME
)
INSERT INTO Schedule (ID, StartTime, EndTime)
VALUES
(2, '2018-02-27 08:00', '2018-02-27 12:00'),
(2, '2018-02-27 13:00', '2018-02-27 17:00')
INSERT INTO UnavailableTimes (ID, StartTime, EndTime)
VALUES
(2, '2018-02-27 07:30', '2018-02-27 08:30'),
(2, '2018-02-27 08:00', '2018-02-27 09:30'),
(2, '2018-02-27 13:30', '2018-02-27 14:00'),
(2, '2018-02-27 16:00', '2018-02-27 18:00')
ID StartTime EndTime
2 2018-02-27 08:00 2018-02-27 12:00
2 2018-02-27 13:00 2018-02-27 17:00
ID StartTime EndTime
2 2018-02-27 07:30 2018-02-27 08:30
2 2018-02-27 08:00 2018-02-27 09:30
2 2018-02-27 13:30 2018-02-27 14:00
2 2018-02-27 16:00 2018-02-27 18:00
ID StartTime EndTime
2 2018-02-27 09:30 2018-02-27 12:00
2 2018-02-27 13:00 2018-02-27 13:30
2 2018-02-27 14:00 2018-02-27 16:00
我想从时间表中的时间范围中减去不可用时间中的时间范围,得到如下可用时间:
可用时间
CREATE TABLE Schedule (
ID INT,
StartTime DATETIME,
EndTime DATETIME
)
CREATE TABLE UnavailableTimes (
ID INT,
StartTime DATETIME,
EndTime DATETIME
)
CREATE TABLE AvailableTimes (
ID INT,
StartTime DATETIME,
EndTime DATETIME
)
INSERT INTO Schedule (ID, StartTime, EndTime)
VALUES
(2, '2018-02-27 08:00', '2018-02-27 12:00'),
(2, '2018-02-27 13:00', '2018-02-27 17:00')
INSERT INTO UnavailableTimes (ID, StartTime, EndTime)
VALUES
(2, '2018-02-27 07:30', '2018-02-27 08:30'),
(2, '2018-02-27 08:00', '2018-02-27 09:30'),
(2, '2018-02-27 13:30', '2018-02-27 14:00'),
(2, '2018-02-27 16:00', '2018-02-27 18:00')
ID StartTime EndTime
2 2018-02-27 08:00 2018-02-27 12:00
2 2018-02-27 13:00 2018-02-27 17:00
ID StartTime EndTime
2 2018-02-27 07:30 2018-02-27 08:30
2 2018-02-27 08:00 2018-02-27 09:30
2 2018-02-27 13:30 2018-02-27 14:00
2 2018-02-27 16:00 2018-02-27 18:00
ID StartTime EndTime
2 2018-02-27 09:30 2018-02-27 12:00
2 2018-02-27 13:00 2018-02-27 13:30
2 2018-02-27 14:00 2018-02-27 16:00
编辑: 在MJH的帮助下,我得到了开始时间和结束时间。现在我只需要把这些放在一起:
;WITH S1 AS (
SELECT U.EndTime AS StartTime
FROM UnavailableTimes U
WHERE NOT EXISTS (
SELECT *
FROM UnavailableTimes W
WHERE U.EndTime BETWEEN W.StartTime AND DATEADD(s, -1, W.EndTime)
)
AND EXISTS (
SELECT *
FROM Schedule S
WHERE U.EndTime BETWEEN S.StartTime AND S.EndTime
)
),
S2 AS (
SELECT S.StartTime
FROM Schedule S
WHERE NOT EXISTS (
SELECT *
FROM UnavailableTimes U
WHERE S.StartTime BETWEEN U.StartTime AND U.EndTime
)
)
SELECT StartTime
FROM S1
UNION ALL
SELECT StartTime
FROM S2
ORDER BY 1
;WITH S1 AS (
SELECT U.StartTime AS EndTime
FROM UnavailableTimes U
WHERE NOT EXISTS (
SELECT *
FROM UnavailableTimes W
WHERE U.StartTime BETWEEN DATEADD(s, 1, W.StartTime) AND W.EndTime
)
AND EXISTS (
SELECT *
FROM Schedule S
WHERE U.StartTime BETWEEN S.StartTime AND S.EndTime
)
),
S2 AS (
SELECT S.EndTime
FROM Schedule S
WHERE NOT EXISTS (
SELECT *
FROM UnavailableTimes U
WHERE S.EndTime BETWEEN U.StartTime AND U.EndTime
)
)
SELECT EndTime
FROM S1
UNION ALL
SELECT EndTime
FROM S2
ORDER BY 1
;WITH S1 AS (
SELECT U.EndTime AS StartTime
FROM UnavailableTimes U
WHERE NOT EXISTS (
SELECT *
FROM UnavailableTimes W
WHERE U.EndTime BETWEEN W.StartTime AND DATEADD(s, -1, W.EndTime)
)
AND EXISTS (
SELECT *
FROM Schedule S
WHERE U.EndTime BETWEEN S.StartTime AND S.EndTime
)
),
S2 AS (
SELECT S.StartTime
FROM Schedule S
WHERE NOT EXISTS (
SELECT *
FROM UnavailableTimes U
WHERE S.StartTime BETWEEN U.StartTime AND U.EndTime
)
),
S3 AS (
SELECT StartTime
FROM S1
UNION ALL
SELECT StartTime
FROM S2
),
S AS (
SELECT StartTime, ROW_NUMBER() OVER(ORDER BY StartTime) RN
FROM S3
),
E1 AS (
SELECT U.StartTime AS EndTime
FROM UnavailableTimes U
WHERE NOT EXISTS (
SELECT *
FROM UnavailableTimes W
WHERE U.StartTime BETWEEN DATEADD(s, 1, W.StartTime) AND W.EndTime
)
AND EXISTS (
SELECT *
FROM Schedule S
WHERE U.StartTime BETWEEN S.StartTime AND S.EndTime
)
),
E2 AS (
SELECT S.EndTime
FROM Schedule S
WHERE NOT EXISTS (
SELECT *
FROM UnavailableTimes U
WHERE S.EndTime BETWEEN U.StartTime AND U.EndTime
)
),
E3 AS (
SELECT EndTime
FROM E1
UNION ALL
SELECT EndTime
FROM E2
),
E AS (
SELECT EndTime, ROW_NUMBER() OVER(ORDER BY EndTime) RN
FROM E3
)
SELECT S.StartTime, E.EndTime
FROM S INNER JOIN E
ON S.RN = E.RN
ORDER BY S.RN
我已经为您破解了开始时间,您应该能够自己解决如何完成结束时间:
;WITH S1 AS (
SELECT U.EndTime AS StartTime
FROM UnavailableTimes U
WHERE NOT EXISTS (
SELECT *
FROM UnavailableTimes W
WHERE U.EndTime BETWEEN W.StartTime AND DATEADD(s, -1, W.EndTime)
)
AND EXISTS (
SELECT *
FROM Schedule S
WHERE U.EndTime BETWEEN S.StartTime AND S.EndTime
)
),
S2 AS (
SELECT S.StartTime
FROM Schedule S
WHERE NOT EXISTS (
SELECT *
FROM UnavailableTimes U
WHERE S.StartTime BETWEEN U.StartTime AND U.EndTime
)
)
SELECT StartTime
FROM S1
UNION ALL
SELECT StartTime
FROM S2
ORDER BY 1
这很好,拼图的最后一部分是将其缝合在一起:
;WITH S1 AS (
SELECT U.EndTime AS StartTime
FROM UnavailableTimes U
WHERE NOT EXISTS (
SELECT *
FROM UnavailableTimes W
WHERE U.EndTime BETWEEN W.StartTime AND DATEADD(s, -1, W.EndTime)
)
AND EXISTS (
SELECT *
FROM Schedule S
WHERE U.EndTime BETWEEN S.StartTime AND S.EndTime
)
),
S2 AS (
SELECT S.StartTime
FROM Schedule S
WHERE NOT EXISTS (
SELECT *
FROM UnavailableTimes U
WHERE S.StartTime BETWEEN U.StartTime AND U.EndTime
)
)
SELECT StartTime
FROM S1
UNION ALL
SELECT StartTime
FROM S2
ORDER BY 1
;WITH S1 AS (
SELECT U.StartTime AS EndTime
FROM UnavailableTimes U
WHERE NOT EXISTS (
SELECT *
FROM UnavailableTimes W
WHERE U.StartTime BETWEEN DATEADD(s, 1, W.StartTime) AND W.EndTime
)
AND EXISTS (
SELECT *
FROM Schedule S
WHERE U.StartTime BETWEEN S.StartTime AND S.EndTime
)
),
S2 AS (
SELECT S.EndTime
FROM Schedule S
WHERE NOT EXISTS (
SELECT *
FROM UnavailableTimes U
WHERE S.EndTime BETWEEN U.StartTime AND U.EndTime
)
)
SELECT EndTime
FROM S1
UNION ALL
SELECT EndTime
FROM S2
ORDER BY 1
;WITH S1 AS (
SELECT U.EndTime AS StartTime
FROM UnavailableTimes U
WHERE NOT EXISTS (
SELECT *
FROM UnavailableTimes W
WHERE U.EndTime BETWEEN W.StartTime AND DATEADD(s, -1, W.EndTime)
)
AND EXISTS (
SELECT *
FROM Schedule S
WHERE U.EndTime BETWEEN S.StartTime AND S.EndTime
)
),
S2 AS (
SELECT S.StartTime
FROM Schedule S
WHERE NOT EXISTS (
SELECT *
FROM UnavailableTimes U
WHERE S.StartTime BETWEEN U.StartTime AND U.EndTime
)
),
S3 AS (
SELECT StartTime
FROM S1
UNION ALL
SELECT StartTime
FROM S2
),
S AS (
SELECT StartTime, ROW_NUMBER() OVER(ORDER BY StartTime) RN
FROM S3
),
E1 AS (
SELECT U.StartTime AS EndTime
FROM UnavailableTimes U
WHERE NOT EXISTS (
SELECT *
FROM UnavailableTimes W
WHERE U.StartTime BETWEEN DATEADD(s, 1, W.StartTime) AND W.EndTime
)
AND EXISTS (
SELECT *
FROM Schedule S
WHERE U.StartTime BETWEEN S.StartTime AND S.EndTime
)
),
E2 AS (
SELECT S.EndTime
FROM Schedule S
WHERE NOT EXISTS (
SELECT *
FROM UnavailableTimes U
WHERE S.EndTime BETWEEN U.StartTime AND U.EndTime
)
),
E3 AS (
SELECT EndTime
FROM E1
UNION ALL
SELECT EndTime
FROM E2
),
E AS (
SELECT EndTime, ROW_NUMBER() OVER(ORDER BY EndTime) RN
FROM E3
)
SELECT S.StartTime, E.EndTime
FROM S INNER JOIN E
ON S.RN = E.RN
ORDER BY S.RN
您正在使用哪个数据库SQL Server(T-SQL)谢谢。这真的很有帮助。我能自己完成最后时刻。再次感谢你。我不知道如何把它们按正确的顺序排列。“ROW_NUMBER()OVER”是答案,我以前从未使用过。不客气,在这一点上,我可能应该指出,这个解决方案可能不会很好地“伸缩”,如果您正在考虑将类似的内容应用到商业产品中,那么最好有一个日历表,其中包含您需要的所有时间增量(例如每15分钟一次),并链接到该日历表。这样就很容易得到不使用的时段。祝你好运