PHP/MYSQL日期时间范围与用户重叠

pet*_*ter 8 php mysql datetime

请为此我需要帮助(为了更好地理解,请参见附图),因为我完全无助.

http://img16.imageshack.us/img16/7196/overlapsen.jpg http://img16.imageshack.us/img16/7196/overlapsen.jpg

如你所见,我有用户,他们将我们的开始和结束日期时间存储在我的数据库中,如YYYY-mm-dd H:i:s.现在我需要根据最常见的时间范围重叠(对于大多数用户)找出所有用户的重叠.我想为大多数用户提供3个最常访问的数据时间重叠.我该怎么做?

我不知道我应该使用哪个mysql查询,或者最好从数据库中选择所有日期时间(开始和结束)并在php中处理它(但是如何?).如图所示,结果应该是例如时间8.30-10.00是用户A + B + C + D的结果.

Table structure:
UserID | Start datetime | End datetime
--------------------------------------
A | 2012-04-03 4:00:00 | 2012-04-03 10:00:00
A | 2012-04-03 16:00:00 | 2012-04-03 20:00:00
B | 2012-04-03 8:30:00 | 2012-04-03 14:00:00
B | 2012-04-06 21:30:00 | 2012-04-06 23:00:00
C | 2012-04-03 12:00:00 | 2012-04-03 13:00:00
D | 2012-04-01 01:00:01 | 2012-04-05 12:00:59
E | 2012-04-03 8:30:00 | 2012-04-03 11:00:00
E | 2012-04-03 21:00:00 | 2012-04-03 23:00:00
Run Code Online (Sandbox Code Playgroud)

nni*_*ols 0

像这样的事情应该让你开始 -

SELECT slots.time_slot, COUNT(*) AS num_users, GROUP_CONCAT(DISTINCT user_bookings.user_id ORDER BY user_bookings.user_id) AS user_list
FROM (
    SELECT CURRENT_DATE + INTERVAL ((id-1)*30) MINUTE AS time_slot
    FROM dummy
    WHERE id BETWEEN 1 AND 48
) AS slots
LEFT JOIN user_bookings
    ON slots.time_slot BETWEEN `user_bookings`.`start` AND `user_bookings`.`end`
GROUP BY slots.time_slot
ORDER BY num_users DESC
Run Code Online (Sandbox Code Playgroud)

这个想法是创建一个由当天的时段组成的派生表。在此示例中,我使用虚拟表(可以是具有与所需集连续的 AI id 的任何表)通过增量添加 30 分钟来创建时隙列表。然后将其结果加入到预订中,以便能够计算每个时段的书籍数量。

更新对于整个日期/时间范围,您可以使用这样的查询来获取所需的其他数据 -

SELECT MIN(`start`) AS `min_start`, MAX(`end`) AS `max_end`, DATEDIFF(MAX(`end`), MIN(`start`)) + 1 AS `num_days`
FROM user_bookings
Run Code Online (Sandbox Code Playgroud)

然后可以将这些值替换到原始查询中,或者可以将两者组合 -

SELECT slots.time_slot, COUNT(*) AS num_users, GROUP_CONCAT(DISTINCT user_bookings.user_id ORDER BY user_bookings.user_id) AS user_list
FROM (
    SELECT DATE(tmp.min_start) + INTERVAL ((id-1)*30) MINUTE AS time_slot
    FROM dummy
    INNER JOIN (
        SELECT MIN(`start`) AS `min_start`, MAX(`end`) AS `max_end`, DATEDIFF(MAX(`end`), MIN(`start`)) + 1 AS `num_days`
        FROM user_bookings
    ) AS tmp
    WHERE dummy.id BETWEEN 1 AND (48 * tmp.num_days)
) AS slots
LEFT JOIN user_bookings
    ON slots.time_slot BETWEEN `user_bookings`.`start` AND `user_bookings`.`end`
GROUP BY slots.time_slot
ORDER BY num_users DESC
Run Code Online (Sandbox Code Playgroud)

编辑我在 中添加了DISTINCTORDER BY子句GROUP_CONCAT()以响应您的最后一个查询。

请注意,您将需要虚拟表中更大范围的 ID。我尚未测试此查询,因此它可能存在语法错误。