如何获取 SQL 可用时间的列表?
How can I fetch a list of available hours in SQL?
这里是用例:客户可以在一个房间里登记一个从一个日期到另一个日期的时间表。我正在尝试实现一个日历,客户可以在其中单击一天并获取可用时间来安排该房间。到目前为止,这是我尝试过的方法,它仅在当天有一个与之关联的时间表时才有效:
SELECT {Hours}.*
FROM {Hours}
WHERE {Hours}.[Id] BETWEEN (
SELECT
CASE
WHEN @DateInput = {Schedule}.[StartDate] THEN 0
WHEN @DateInput > {Schedule}.[StartDate] AND @DateInput < {Schedule}.[EndDate] THEN 23
WHEN @DateInput = {Schedule}.[EndDate] THEN {Schedule}.[EndHour]
END
FROM {Schedule}
WHERE {Schedule}.[RoomId] = @RoomInput
) AND (
SELECT
CASE
WHEN @DateInput = {Schedule}.[StartDate] THEN {Schedule}.[StartHour] - 1
WHEN @DateInput > {Schedule}.[StartDate] AND @DateInput < {Schedule}.[EndDate] THEN 0
WHEN @DateInput = {Schedule}.[EndDate] THEN 23
END
FROM {Schedule}
WHERE {Schedule}.[RoomId] = @RoomInput
)
我不熟悉像 {Hours}
这样的花括号表示法,但我会假设这是一个外部系统的东西并且 运行 用它。
我相信您需要将查询结构化为 select 小时,而不是两个值之间的 select 小时,这不是任何现有计划条目的一部分。这可以通过 NOT EXISTS() 条件来完成。类似于:
SELECT H.*
FROM {Hours} H
WHERE NOT EXISTS (
SELECT *
FROM {Schedule} S
WHERE S.RoomId = @RoomInput
AND (S.StartDate < @DateInput
OR (S.StartDate = @DateInput AND S.StartHour <= H.Id))
AND (S.EndDate > @DateInput
OR (S.EndDate = @DateInput AND S.EndHour >= H.Id))
)
如果将日期和时间结合起来,这样的比较通常更容易编写。
WHERE S.RoomId = @RoomInput
AND DATEADD(hour, H.Id, @DateInput)
BETWEEN DATEADD(hour, S.StartHour, S.StartDate)
AND DATEADD(hour, S.EndHour, S.EndDate)
您可能需要根据 EndDate 是包含还是排除来调整结束比较。 (EndHour = 10 的计划条目是否在 10:00 或 11:00 结束?)
有关工作演示,请参阅
- this db<>fiddle 使用包含日期。
- this db<>fiddle 使用唯一的结束日期(上午 9 点开始的 1 小时会议的 EndHour = 10)。
- this db<>fiddle 使用组合 date/times 和独占结束 date/time.
这里是用例:客户可以在一个房间里登记一个从一个日期到另一个日期的时间表。我正在尝试实现一个日历,客户可以在其中单击一天并获取可用时间来安排该房间。到目前为止,这是我尝试过的方法,它仅在当天有一个与之关联的时间表时才有效:
SELECT {Hours}.*
FROM {Hours}
WHERE {Hours}.[Id] BETWEEN (
SELECT
CASE
WHEN @DateInput = {Schedule}.[StartDate] THEN 0
WHEN @DateInput > {Schedule}.[StartDate] AND @DateInput < {Schedule}.[EndDate] THEN 23
WHEN @DateInput = {Schedule}.[EndDate] THEN {Schedule}.[EndHour]
END
FROM {Schedule}
WHERE {Schedule}.[RoomId] = @RoomInput
) AND (
SELECT
CASE
WHEN @DateInput = {Schedule}.[StartDate] THEN {Schedule}.[StartHour] - 1
WHEN @DateInput > {Schedule}.[StartDate] AND @DateInput < {Schedule}.[EndDate] THEN 0
WHEN @DateInput = {Schedule}.[EndDate] THEN 23
END
FROM {Schedule}
WHERE {Schedule}.[RoomId] = @RoomInput
)
我不熟悉像 {Hours}
这样的花括号表示法,但我会假设这是一个外部系统的东西并且 运行 用它。
我相信您需要将查询结构化为 select 小时,而不是两个值之间的 select 小时,这不是任何现有计划条目的一部分。这可以通过 NOT EXISTS() 条件来完成。类似于:
SELECT H.*
FROM {Hours} H
WHERE NOT EXISTS (
SELECT *
FROM {Schedule} S
WHERE S.RoomId = @RoomInput
AND (S.StartDate < @DateInput
OR (S.StartDate = @DateInput AND S.StartHour <= H.Id))
AND (S.EndDate > @DateInput
OR (S.EndDate = @DateInput AND S.EndHour >= H.Id))
)
如果将日期和时间结合起来,这样的比较通常更容易编写。
WHERE S.RoomId = @RoomInput
AND DATEADD(hour, H.Id, @DateInput)
BETWEEN DATEADD(hour, S.StartHour, S.StartDate)
AND DATEADD(hour, S.EndHour, S.EndDate)
您可能需要根据 EndDate 是包含还是排除来调整结束比较。 (EndHour = 10 的计划条目是否在 10:00 或 11:00 结束?)
有关工作演示,请参阅
- this db<>fiddle 使用包含日期。
- this db<>fiddle 使用唯一的结束日期(上午 9 点开始的 1 小时会议的 EndHour = 10)。
- this db<>fiddle 使用组合 date/times 和独占结束 date/time.