1

如果我将数据存储在这样的数据库中。

fk    start    end
1     1000     1100
1     1030     1130
2     1000     1100

如何编写查询,以便获得如下结果:

fk    timeslot    occurences
1     1000        1
1     1030        2
1     1100        1
2     1000        1
2     1030        1

正如你所知道的,我以 30 分钟为增量工作。我可以实现这个服务器端,但它需要我运行查询查询或每次都点击数据库,计算两次之间的行数。如果我可以在 1 个查询中收集这些信息,我的整个系统将会快得多。

FK 是我正在保留的资源的 ID。

基本上,我想让用户知道根据数据库中的发生情况还剩下多少个开放点,如果可能的话,不会多次访问数据库。如果我必须在一天中每增加 30 分钟运行一次,即使是 QoQ 也会受到伤害。

您还可以假设 fk 1 和 2 如果重要的话,我有一个已知的最大开始时间和最大结束时间。

4

1 回答 1

2

您必须首先以某种方式创建所有时隙,以便您拥有可以检查预订的东西。递归CTE最适合这样的事情。因此,使用可以使用这个CTE

DECLARE @MinStart TIME = '10:00:00'
DECLARE @MaxEnd TIME   = '12:00:00'

;WITH Timeslots AS (
   SELECT SlotStart = @MinStart, 
          SlotEnd = DATEADD(MINUTE, 30, @MinStart)

   UNION ALL

   SELECT SlotStart = DATEADD(MINUTE, 30, SlotStart), 
          SlotEnd = DATEADD(MINUTE, 30, SlotEnd)
   FROM Timeslots
   WHERE SlotEnd < @MaxEnd
)
SELECT *
FROM Timeslots

生成下表表达式:

SlotStart           SlotEnd
------------------------------------
10:00:00.0000000    10:30:00.0000000
10:30:00.0000000    11:00:00.0000000
11:00:00.0000000    11:30:00.0000000
11:30:00.0000000    12:00:00.0000000

10:00这些都是和之间的时隙12:00

您现在可以使用此查询:

;WITH Timeslots AS (
  ... cte statement here ...
)
SELECT fk, COUNT(fk) AS occurrences, t.SlotStart, t.SlotEnd
FROM #Reservations AS r
INNER JOIN Timeslots AS t ON t.SlotStart >= r.start AND t.SlotEnd <= r.[end]
GROUP BY fk, t.SlotStart, t.SlotEnd

得到你想要的结果:

fk  occurrences SlotStart           SlotEnd
---------------------------------------------
1   1           10:00:00.0000000    10:30:00.0000000
1   2           10:30:00.0000000    11:00:00.0000000
1   1           11:00:00.0000000    11:30:00.0000000
2   1           10:00:00.0000000    10:30:00.0000000
2   1           10:30:00.0000000    11:00:00.0000000
于 2015-01-28T16:51:52.690 回答