【问题标题】:Search for free times in calendar with MySQL使用 MySQL 在日历中搜索空闲时间
【发布时间】:2020-07-09 06:38:51
【问题描述】:

我有一个用户表,我在其中保存用户信息以及他们一天的开始和结束时间

id    day_start    day_end
1     08:00:00     16:00:00
2     09:00:00     18:00:00        

还有另一个表格保存用户的日历事件

id    user_id    start                    end
1     1          2020-01-12 12:00:00      2020-01-12 13:30:00
2     1          2020-01-12 13:30:00      2020-01-12 14:30:00
3     1          2020-01-12 09:00:00      2020-01-12 10:30:00

所以我试图根据他们的空闲时间来过滤这些人。即我想提供开始时间、结束时间和一周中的几天的数组,并根据这些标准找到可用的用户。 例如,我想说我正在寻找周六或周一 10:00:00 到 14:00:00 之间任何时间有空的人,并收到用户列表。

请注意,用户可能无法在整个请求的时间内有空,而只是一小部分时间。例如,周六 11:00:00 到 11:30:00 只有空闲时间的用户也应该被列出。

我正在寻找一个 MySQL 查询来实现这个功能。

如果查询可以给出所有空闲时间段的开始和结束时间,那就太好了。 像这样的

user_id    start                    end
1          2020-01-12 08:00:00      2020-01-12 09:00:00
1          2020-01-12 10:30:00      2020-01-12 12:00:00
1          2020-01-12 14:30:00      2020-01-12 18:00:00
2          ...
...

【问题讨论】:

    标签: mysql sql date datetime join


    【解决方案1】:

    这是一个使用窗口函数和公共表表达式的选项(两者都仅在 MySQL 8.0 中可用)。

    首先,您可以加入两个表并使用lag() 来结束previous 事件。然后,您可以通过搜索不相邻的行来提取间隔。第一个间隔由它没有先前事件的事实来识别。要获得最后一个区间,我们使用union all 并再次从 cte 中选择。

    with cte as (
        select
            e.*,
            u.day_start,
            u.day_end,
            lag(e.dt_end) over(partition by u.id order by e.dt_start) lag_dt_end
        from events e
        inner join users u on u.id = e.user_id
    )
    select
        user_id,
        coalesce(lag_dt_end, concat(date(dt_start), ' ', day_start)) dt_start,
        dt_start dt_end
    from cte
    where 
        dt_start <> lag_dt_end 
        or (lag_dt_end is null and time(dt_start) > day_start)
    union all
    select 
        user_id, 
        max(dt_end), 
        concat(date(max(dt_end)), ' ', day_end)
    from cte
    group by user_id, day_end
    having time(max(dt_end)) < day_end
    

    Demo on DB Fiddle

    用户 ID | dt_start | dt_end ------: | :----------------- | :----------------- 1 | 2020-01-12 08:00:00 | 2020-01-12 09:00:00 1 | 2020-01-12 10:30:00 | 2020-01-12 12:00:00 1 | 2020-01-12 14:30:00 | 2020-01-12 16:00:00

    【讨论】:

    • 感谢您的回复,这种方法的性能如何?我的意思是为了更简单的查询而改变数据库结构是否值得?
    猜你喜欢
    • 1970-01-01
    • 2012-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多