mysql - SQL/Mysql 查询数据库中可用的日期和时间

标签 mysql sql date laravel-5 calendar

我需要一些帮助来查询我的日历/日期表

场景:我有一个包含日期和时间的“日历”表(见下文),用户将设置他们的可用日期,通常是每天都有可用的时段。所以我的 table 看起来像这样:

+------+------------+---------------------+---------------------+ 
| 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 我希望查询进行检查以下:

    • 查看用户每天在这些时间是否有空。
    • 在本例中,用户是否可以在 2016 年 9 月 3 日 08:00:00 到 16:00:00 之间以及 2016 年 9 月 4 日 08:00:00 到 16:00 之间有空: 00.
    • 在此示例中应返回用户 1。

如果需要,我愿意接受重新设计我的架构的建议。

希望有人可以帮助我。

最佳答案

<强> 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`);

输出

  • 第 1 步:创建日期列表,在本例中为 273 年
  • 第 2 步:选择参数中定义的范围内的所有日期,还包括每个日期的时间窗口。
  • 第 3 步:将所有内容结合起来,查看用户在该时间窗口内的日期
  • 第 4 步:仅选择具有所有日期时间范围的用户

enter image description here

关于mysql - SQL/Mysql 查询数据库中可用的日期和时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40796172/

相关文章:

返回最接近 R 中给定日期的日期

mysql - 为什么 phpmyadmin 拒绝通过本地主机连接但接受 127.0.0.1?

php - 每月佣金计算 PHP

mysql - mySQL 的速度和调整(10 亿行)

javascript - 在 Javascript 中格式化日期,得到未定义的 NaN

android - 如何在 android 中获取 WEEK_OF_YEAR 内的日期列表?

php - 创建php fom从表bd中选择多个取值

sql - 如何删除子表中的数据?

sql - 在 Pycharm 中安装 pymssql 2.1.3

sql - Rails 应用程序中的原始 pg GROUP BY 查询