在WHERE子句中将行与相邻的时间戳组合在一起

时间:2012-03-16 10:14:40

标签: mysql

我有一个表availablities,其中包含用户的可用性:

row_id | user_id  | available_from      | available_to
-------------------------------------------------------------
1      | 1        | 2012-02-01 08:00:00 | 2012-02-01 09:00:00
2      | 1        | 2012-02-01 09:00:00 | 2012-02-01 10:00:00
3      | 2        | 2012-02-01 08:00:00 | 2012-02-01 10:00:00
4      | 3        | 2012-02-01 07:00:00 | 2012-02-01 12:00:00

我需要从此表中获取特定事件的所有可用用户。

场景:获取以2012-02-01 08:00:00开头并结束2012-02-01 10:00:00的活动的所有可用用户。

获取user_ids (2,3)时没问题:

SELECT `user_id` FROM `availablities`
WHERE `available_from` <= "2012-02-01 08:00:00"
AND `available_to` >= "2012-02-01 10:00:00"

我很难找到一个也会返回user_id (1)的查询。为此,查询必须显示组合(1)的{​​{1}}和(2)两行,因为只有这两个可用性的总和符合事件。

在完美的世界中,行user_id (1)上的相邻可用性将只在一行中。有理由以这种方式保存它,我不能只是“优化”表格中的数据来组合一行中的相邻可用性。

所以我需要的是mysql在给定时间范围内在一个查询中返回(1,2)的方法 - 可能还是我必须找到另一种方法?

1 个答案:

答案 0 :(得分:1)

如果您需要在一个查询中执行此操作,您可以尝试组合MySQL用户定义变量和一些内联视图技巧:

select  d.*
from
(
select u.user_id,u.consec as available_from,max(u.available_to) as available_to
from
(
select a.*,
case when @lastEndDate != a.available_from then @curStartDate := a.available_from else @curStartDate end as consec,
@lastEndDate := a.available_to as c
from availabilities a
inner join (select @curStartDate := null,@lastEndDate := "1970-01-01 00:00:00") as t
order by a.user_id,a.available_from
) u
group by u.user_id,u.consec
) d
where d.available_from <= "2012-02-01 08:00:00"
AND d.available_to >= "2012-02-01 10:00:00";

我拿了你的测试数据并包括一个用户(user_id = 4),他在2012-02-01 08:00:00和2012-02-01 08:30:00之间可用,然后再在2012年之间-02-01 09:00:00和2012-02-01 10:00:00所以他在2012-02-01 08:00:00和2012-02-01 10:00:00(喝咖啡休息时间?!)之间的整段时间都没空。

因此预期的结果是在该时间段内返回user_id = 1但是user_id = 4不是。

以下是我使用的测试:

drop table if exists availabilities;

create table availabilities
(row_id integer unsigned not null primary key,
user_id integer not null,
available_from datetime not null,
available_to datetime not null
);

insert into availabilities values (1,1,'2012-02-01 08:00:00','2012-02-01 09:00:00');
insert into availabilities values (2,1,'2012-02-01 09:00:00','2012-02-01 10:00:00');
insert into availabilities values (3,2,'2012-02-01 08:00:00','2012-02-01 10:00:00');
insert into availabilities values (4,3,'2012-02-01 07:00:00','2012-02-01 12:00:00');
insert into availabilities values (5,4,'2012-02-01 08:00:00','2012-02-01 08:30:00');
insert into availabilities values (6,4,'2012-02-01 09:00:00','2012-02-01 10:00:00');