我有一个MySQL数据库中的预留列表,我想确定以15分钟为间隔保留的总时隙数。要做到这一点,我需要“展开”(可能不是正确的单词)每个预订,确定重叠,并显示总使用量。
该表是预订列表:
ResID StartTime EndTime SlotsUsed
1 2010-06-13 12:00:00 2010-06-13 12:59:00 10
2 2010-06-13 12:00:00 2010-06-13 12:29:00 5
3 2010-06-13 12:30:00 2010-06-13 13:29:00 15
我想要的输出是这样的:
Time SlotsInUse
2010-06-13 12:00:00 15
2010-06-13 12:15:00 15
2010-06-13 12:30:00 25
2010-06-13 12:45:00 25
2010-06-13 13:00:00 15
在SQL之外,我可以很容易地使用日期时间数学&列表/数组。但是无论如何要在SELECT语句本身中执行它,以某种方式对项目进行正确的分组,并使用sum()
?
答案 0 :(得分:1)
这样做的诀窍是获取一个间隔列表。为此,您需要一个Numbers或Tally表,它是一个包含整数顺序列表的静态表。
Create Temporary Table Test
(
ResId int not null
, StartTime datetime not null
, EndTime datetime not null
, SlotsUsed int not null
)
Insert Test(ResId, StartTime, EndTime, SlotsUsed) Values(1, '2010-06-13 12:00:00','2010-06-13 12:59:00',10)
Insert Test(ResId, StartTime, EndTime, SlotsUsed) Values(2, '2010-06-13 12:00:00','2010-06-13 12:29:00',5 )
Insert Test(ResId, StartTime, EndTime, SlotsUsed) Values(3, '2010-06-13 12:30:00','2010-06-13 13:29:00',15 )
------
Create Temporary Table Numbers ( Value int not null )
Insert Numbers(Value) Values(1)
Insert Numbers(Value) Values(2)
Insert Numbers(Value) Values(3)
Insert Numbers(Value) Values(4)
Insert Numbers(Value) Values(5)
Insert Numbers(Value) Values(6)
...
Select Intervals.[Date], Sum(SlotsUsed)
From (
Select Date_Add( '2010-06-13 12:00:00', INTERVAL + (15 * N.Value) MINUTE ) As [Date], T.SlotsUsed
From Test As T
Join Numbers As N
On Date_Add( '2010-06-13 12:00:00', INTERVAL + (15 * N.Value) MINUTE ) Between T.StartTime And T.EndTime
) As Intervals
Group By Intervals.[Date]
在这里,我随意选择2010-06-13 12:00:00
作为确定间隔的开始时间。但是,只要您的Numbers表大到足以计算给定日期内的所有间隔(即至少有96个值),您就可以轻松使用DATE(T.StartTime)
。
答案 1 :(得分:0)
你可以做的是事先查询总范围,这样你就有了结束时间。然后,您可以使用UNION生成一个巨大的SQL,它将为您提供所有这些间隔的结果,如下所示:
SELECT Sum(SlotsUsed), $interval1 FROM table WHERE startime <= $interval1 AND endtime >= $interval1
UNION
SELECT Sum(SlotsUsed), $interval2 FROM table WHERE startime <= $interval2 AND endtime >= $interval2
UNION
...
然而,如果这是可行的话,那就没有任何线索了。
在DB2中,你可以这样做来改善查询的大小,也许在MySQL中有类似的东西:
SELECT Sum(SlotsUsed), I.Interval
FROM table, (VALUES ($interval1), ($interval2), ..., ($intervalN) ) I(Interval)
WHERE table.startime <= I.Interval AND table.endtime >= I.Interval
GROUP BY I.Interval
答案 2 :(得分:0)
这可能对你有用。我没有测试它,当我翻译成实际的sql时,我通常必须修复我的SQL ...
select time,sum(slotsused) from temp left outer join reservations on timetable between(starttime,endtime)
group by time
答案 3 :(得分:0)
我建议使用循环。您可以在Database Journal找到有关循环的更多信息。
我不确定如何但是如果你可以将每次循环结果组合在一起将insert语句更改为select。但是因为我不知道如何做到这一点,或者如果有可能,你可以更容易地创建一个临时表,然后只需select *
。这是未经测试的伪代码,但您可以执行以下操作:
Create tempTable Values ResID, StartTime, EndTime, SlotsUsed
Declare @min datetime
Declare @max datetime
Set @min = (SELECT MIN(StartTime) FROM Table)
Set @max = (SELECT MAX(EndTime) FROM Table)
Some how round @min to nearest hour or 15 minute increment
for example : 2010-06-13 12:10:00 to 2010-06-13 12:00:00
2010-06-13 12:34:00 to 2010-06-13 12:00:00 OR 2010-06-13 12:30:00
DECLARE @case_exit int
SET @counter = 0
while @counter < 1
begin
insert into tempTable Time = @min, SlotsInUse = (
SELECT SUM(SlotsUsed) FROM table WHERE @min => StartTime AND @min =< EndTime)
@min = @min + 15 minutes
end
SELECT * from TempTable