我需要一些帮助来查询我的日历/日期表
场景:我有一个"日历"如果日期和时间表(见下文),用户将设置他们的可用日期,通常是每天可用的时间段。所以我的表看起来像这样:
+------+------------+---------------------+---------------------+
| ID | user_id | start_date | end_date |
+------+------------+---------------------+---------------------+
| 1 | 1 | 2016-09-01 08:00:00 | 2016-09-01 16:00:00 |
| 2 | 1 | 2016-09-03 00:00:00 | 2016-09-03 23:59:59 |
| 3 | 1 | 2016-09-04 00:00:00 | 2016-09-04 16:00:00 |
| 4 | 1 | 2016-09-05 08:00:00 | 2016-09-05 16:00:00 |
| 5 | 2 | 2016-09-05 08:00:00 | 2016-09-05 16:00:00 |
| 6 | 2 | 2016-09-07 08:00:00 | 2016-09-07 16:00:00 |
| 7 | 2 | 2016-09-08 08:00:00 | 2016-09-08 16:00:00 |
| 8 | 2 | 2016-09-08 18:00:00 | 2016-09-08 22:00:00 |
+------+------------+---------------------+---------------------+
我们这里有2个用户,所以我想要以下内容:
如果我搜索start_date = 2016-09-05 08:00:00和end_date = 2016-09-05 16:00:00它应该返回用户1和2.因为它们都有一个条目与这些日期。同样如果start_date = 2016-09-05 09:00:00和end_date = 2016-09-05 15:00:00,这也应该返回两个用户,因为我搜索的时间是在时间段之间示例中显示。
第二种情况有点棘手,如果用户搜索start_date = 2016-09-03 08:00:00和end_date = 2016-09-04 16:00:00我希望查询检查以下内容:
我可以根据需要重新设计我的架构。
希望有些人可以帮助我。
答案 0 :(得分:0)
DEMO 包含一些附加代码注释,并显示查询的演变方式。另外,我为user_id = 2
添加了另一行,以显示如何仅匹配范围内两天中的一天。
SELECT U.`user_id`
FROM (
select a.selectDate,
CONCAT(a.selectDate, ' ', time(@s_date)) as start_time,
CONCAT(a.selectDate, ' ', time(@s_date)) as end_time
from (
select '1900-01-01' + INTERVAL (a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a) + (10000 * e.a)) DAY as selectDate
from (select 0 as a 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) as a
cross join (select 0 as a 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) as b
cross join (select 0 as a 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) as c
cross join (select 0 as a 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) as d
cross join (select 0 as a 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) as e
) a
CROSS JOIN (SELECT @s_date := '2016-09-03 08:00:00', @e_date := '2016-09-04 16:00:00') par
-- CROSS JOIN (SELECT @s_date := '2016-09-05 08:00:00', @e_date := '2016-09-05 16:00:00') par
-- CROSS JOIN (SELECT @s_date := '2016-09-05 09:00:00', @e_date := '2016-09-05 15:00:00') par
WHERE selectDate BETWEEN date(@s_date)
AND date(@e_date)
) D
CROSS JOIN (SELECT DISTINCT `user_id` FROM Table1) U
LEFT JOIN Table1 T
ON U.`user_id` = T.`user_id`
AND D.start_time <= T.`end_date`
AND D.end_time >= T.`start_date`
GROUP BY U.`user_id`
HAVING COUNT(U.`user_id`) = COUNT(T.`user_id`);
<强>输出强>