在这种情况下双重加入这张表是个好主意吗?

问题描述 投票:0回答:0

过去几天我一直在努力想出解决我的建模问题的方法。

我有实体 Event 它将有 1 个或多个 EventDay(s),这将代表给定日期中的连续时间段。例如活动 A 有 2 个活动日:

  • EventDay 1 - 日期:10.10.2000;开始于:10:00,结束于:17:30
  • EventDay 2 - 日期:11.10.2000;开始时间:09:30,结束时间:12:00

然后我有 User,他可以设置自己的 Schedule,对于一周中的任何一天,它应该是 1 个或多个连续的时间段。这表示他有空参加活动的时间。例如用户 B 有以下时间表:

  • 周一:08:00 - 15:00、17:00 - 19:00
  • 周二:10:00 - 20:00
  • 周三:12:00-13:30、15:00-17:00、20:00-22:30
  • ...一周中的每一天都一样

我想要实现的是获取一个 User 可以参与的所有 Events 的列表,按照与用户的日程安排匹配的 EventDays 排名,以及所有活动天数的一些统计数据(例如,所有天的总小时数,而不仅仅是与用户的日程安排相匹配的小时数)。

一个很好的补充是能够按一个或多个工作日过滤事件。 (例如,我正在寻找只有周一和周二有活动日的活动)

首先我会提到时间段必须是 30 分钟的倍数——因此,在数据库中我将小时 00:00 存储为整数 0,00:30 存储为整数 1,依此类推直到 24:00 作为 int 48

活动

id 姓名
1 事件A

活动日

id event_id 约会 开始于 结束于
1 1 10.10.2000 20 35
2 1 11.10.2000 19 24

时间表

id user_id 开始于 结束于
1 1 0 16 30
2 1 0 34 38
3 1 1 20 40
4 1 2 24 27
5 1 2 30 34
6 1 2 40 45

这里的日列在 0..6 范围内,代表星期几。

为了得到想要的结果,我提出了以下查询:

SELECT
    event.id,
    SUM(unfiltered_event_day.ending_at - unfiltered_event_day.starting_at) as total_event_hours,
FROM events event
         INNER JOIN event_days event_day ON event.id = event_day.event_id
         INNER JOIN event_days unfiltered_event_day ON event.id = unfiltered_event_day.event_id
         INNER JOIN schedules schedule ON EXTRACT(ISODOW FROM event_day.date) - 1 = schedule.day
WHERE
        schedule.user_id = :userId AND 
        EXTRACT(ISODOW FROM event_day.date) - 1 in :listOfdays AND
        event_day.starting_at >= schedule.starting_at AND
        event_day.ending_at <= schedule.ending_at
GROUP BY event.id
ORDER BY count(event.id) DESC, MIN(event_day.date)

EXTRACT(ISODOW FROM event_day.date) - 1 从日期中获取星期几

这种方法在性能方面有什么好处吗?我已经尝试了一些其他方法来对此建模,但这个似乎是性能最高的。

另一种方法是使用一个只读表,其中包含给定日期内所有可能的时间段组合(00:00-00:30、00:00-01:00、...、23:30-24 :00),以及它和User之间以及它和Event之间的m:n关系。这里的想法是我会双重加入时间段表,但因为它是只读的,所以它不会那么昂贵,因为它总是有一个相对较小的尺寸。

你们看到我的方法有什么缺点或改进吗?我真的很难全神贯注于建模这个

sql join self-join
© www.soinside.com 2019 - 2024. All rights reserved.