MySQL查询:SUM条件过滤及筛选最后追踪记录超两周的用户
解决方案
问题1:聚合函数无法在WHERE子句中使用的解决方法
SUM()属于聚合函数,是对分组后的结果进行计算的,而WHERE子句是在分组之前过滤行数据,因此不能直接在WHERE里使用聚合函数判断。你需要把总时长的判断逻辑放到HAVING子句中,HAVING是专门用来过滤分组后的结果的。
问题2:筛选用户最新追踪记录超过两周的方法
假设你的timers表中有记录追踪时间的字段(比如created_at,如果实际字段名不同请替换),可以通过MAX(t.created_at)获取每个用户的最后一次追踪时间,然后判断这个时间是否早于当前日期减去14天(用DATE_SUB(NOW(), INTERVAL 14 DAY)实现)。这个判断同样要放到HAVING子句中,因为它也是基于分组后的聚合结果。
完整查询语句
SELECT u.id, u.firstname, u.track_outdoors, COALESCE(SUM(t.total_time), 0) AS total, -- 处理无追踪记录的用户,总时长显示为0 MAX(t.created_at) AS last_track_time FROM users AS u LEFT JOIN timers AS t ON u.id = t.user_id WHERE u.track_outdoors = 1 AND JSON_EXTRACT(u.meta, '$.ac_outdoors_outdoors_reminder_sent_at') IS NULL GROUP BY u.id, u.firstname, u.track_outdoors -- MySQL 5.7+需要把SELECT中非聚合的字段都放到GROUP BY里 HAVING total < 1000 -- 累计时长未超过1000小时 AND (last_track_time < DATE_SUB(NOW(), INTERVAL 14 DAY) OR last_track_time IS NULL) -- 上面的OR last_track_time IS NULL是处理从未有过追踪记录的用户,如果不需要包含这类用户,可以去掉这部分,或者把LEFT JOIN改成INNER JOIN
补充说明
- 如果你的
timers表中记录追踪时间的字段不是created_at,请替换为实际字段名(比如updated_at)。 COALESCE(SUM(t.total_time), 0)是为了让没有任何追踪记录的用户总时长显示为0,避免出现NULL值。- 如果不需要包含从未进行过追踪的用户,只需将
LEFT JOIN改为INNER JOIN,同时去掉HAVING中的OR last_track_time IS NULL即可。
内容的提问来源于stack exchange,提问作者Mosh
相关产品推荐
相关产品推荐

