如果用户“会话”的概念对您的分析很重要,那么我将开始在您的表中记录数据,以便查询与会话相关的数据不是一个痛苦的过程。一个简单的方法是记录您的 PHP 会话 ID。如果您的 PHP 会话 ID 设置为具有相同的 30 分钟到期时间,并且您将 PHP 会话 ID 记录到此表中,那么您基本上将拥有您正在寻找的内容。
当然,这对您现有的记录没有帮助。我可能会继续创建会话字段,然后用随机生成的“会话”ID 重新填充它。我不会为此寻找一个完整的 SQL 解决方案,因为它在处理边缘情况(跨天的会话等)方面可能无法满足您的要求。我会编写一个脚本来执行此回填,其中将包含您需要的所有逻辑。
我的一般方法是像这样选择所有记录:
SELECT user_id, date /* plus any other fields like unique id that you would need for insert */
FROM Article_Impressions
WHERE session_id IS NULL
ORDER BY user_id ASC, date ASC
注意:确保您在 user_id 和 date 字段上都有索引。
然后,我将遍历结果集,构建每个 user_id 的临时数组,并遍历该数组以获取所有日期值,并分配一个随机生成的会话 id,每次日期更改大于 30 分钟时该会话 id 都会更改。一旦用户值增加,我将为该前一个用户进行插入以更新 session_id 值,然后将临时数组重置为空并继续与下一个用户进行该过程。
请注意,采取像这样保持相对较小的临时/工作数组的方法可能很重要,因为您正在谈论的记录数,您可能无法将整个结果集读入数组在记忆中。
填充数据后,查询变得微不足道:
每天的独特会话:
SELECT DATE(date) as `day`, COUNT(DISTINCT session_id) AS `unique_sessions`
FROM Article_Impressions
GROUP BY `day`
ORDER BY `day` DESC /* or ASC depending on how you want to view it */
每天平均会话数:
SELECT AVG(sessions_per_day.`unique_sessions`) AS `average_sessions_per_day`
FROM
(
SELECT DATE(date) as `day`, COUNT(DISTINCT session_id) AS `unique_sessions`
FROM Article_Impressions
GROUP BY `day`
) AS sessions_per_day
GROUP BY sessions_per_day.`day`
注意:您需要新 session_id 字段的索引。