我想从数据库表中找出用户的可用性:
primary id | UserId | startdate | enddate
1 | 42 | 2014-05-18 09:00 | 2014-05-18 10:00
2 | 42 | 2014-05-18 11:00 | 2014-05-18 12:00
3 | 42 | 2014-05-18 14:00 | 2014-05-18 16:00
4 | 42 | 2014-05-18 18:00 | 2014-05-18 19:00
让我们考虑上面插入的数据是用户的忙碌时间,我想在开始时间和结束时间之间找出表中的空闲时间间隔块。
BETWEEN 2014-05-18 11:00 AND 2014-05-18 19:00;
让我在这里添加表格模式以避免混淆:
Create Table availability (
pid int not null,
userId int not null,
StartDate datetime,
EndDate datetime
);
Insert Into availability values
(1, 42, '2013-10-18 09:00', '2013-10-18 10:00'),
(2, 42, '2013-10-18 11:00', '2013-10-18 12:00'),
(3, 42, '2013-10-18 14:00', '2013-11-18 16:00'),
(4, 42, '2013-10-18 18:00', '2013-11-18 19:00');
需要量: 我想找出像这样的免费差距记录:
'2013-10-27 10:00' to '2013-10-28 11:00' - User is available for 1 hours and
'2013-10-27 12:00' to '2013-10-28 14:00' - User is available for 2 hours and
available start time is '2013-10-27 10:00' and '2013-10-27 12:00' respectively.
答案 0 :(得分:1)
你去吧
SELECT t1.userId,
t1.enddate, MIN(t2.startdate),
MIN(TIMESTAMPDIFF(HOUR, t1.enddate, t2.startdate))
FROM user t1
JOIN user t2 ON t1.UserId=t2.UserId
AND t2.startdate > t1.enddate AND t2.pid > t1.pid
WHERE
t1.endDate >= '2013-10-18 09:00'
AND t2.startDate <= '2013-11-18 19:00'
GROUP BY t1.UserId, t1.endDate
答案 1 :(得分:0)
使用您的数据,最简单的方法是列出某人空闲时的小时数。以下是有人可用的小时列表:
select (StartTime + interval n.n hour) as FreeHour
from (select cast('2014-05-18 11:00' as datetime) as StartTime,
cast('2014-05-18 19:00' as datetime) as EndTime
) var join
(select 0 as n union all select 1 union all select 2 union all select 3 union all select 4 union all
select 5 union all select 6 union all select 7 union all select 8 union all select 9
) n
on StartTime + interval n.n hour <= EndTime
where not exists (select 1
from availability a
where StartTime + interval n.n hour < a.EndDate and
StartTime + interval n.n hour >= a.StartDate
);
编辑:
您的问题的一般解决方案需要对数据进行非规范化。基本查询是:
select thedate, sum(isstart) as isstart, @cum := @cum + sum(isstart) as cum
from ((select StartDate as thedate, 1 as isstart
from availability a
where userid = 42
) union all
(select EndDate as thedate, -1 as isstart
from availability a
where userid = 42
) union all
(select cast('2014-05-18 11:00' as datetime), 0 as isstart
) union all
(select cast('2014-05-18 19:00' as datetime), 0 as isstart
)
) t
group by thedate cross join
(select @cum := 0) var
order by thedate
然后,您只需选择cum = 0
的值。挑战是从这个列表中获取下一个日期。在MySQL中这是一个真正的痛苦,因为你不能使用CTE或视图或窗口函数,所以你必须重复查询。这就是为什么我认为第一种方法可能对你的情况更好。
答案 2 :(得分:0)
核心查询可以是这个。你可以随意打扮,但我会在表现层中处理所有这些......
SELECT a.enddate 'Available From'
, MIN(b.startdate) 'To'
FROM user a
JOIN user b
ON b.userid = a.user
AND b.startdate > a.enddate
GROUP
BY a.enddate
HAVING a.enddate < MIN(b.startdate)
对于“预订”范围之外的时间,您必须使用UNION扩展一点,或者再次处理应用程序级别的逻辑