[英]Sql query that selects all inactive users
我有一个查询要实现。
我有2个表: user和login_logs表。
用户表如下所示:
id || first_name || last_name || 电子邮件 || 用户名 || 激活 || 暂停
1 || 约翰|| 丹|| john @ whatever || john1 || 1 || 0 ||
2 || 迈克|| 哈特|| mike @ whatever || mike1 || 1 || 0 ||
等等
login_logs表如下所示:
id || login_datetime || 用户身份
1 || 2011-01-27 23:04:59 || 1
2 || 2010-01-27 23:04:59 || 2
等等
因此login_logs表记录用户何时登录。
现在我想创建一个选择所有非活动用户的查询。 非活动用户是:
1)未登录90天的用户
2)从未登录的用户
我做了一个满足第一个条件但不完全正确的查询:
SELECT DISTINCT u.id, u.last_name, u.first_name, u.email,u.username
FROM users u INNER JOIN login_logs l ON l.user_id = u.id
WHERE u.activated = 1 AND u.suspended = 0 AND DATEDIFF(CURDATE(), l.login_datetime) <= 90
ORDER BY u.last_name, u.first_name, u.id
以上查询不正确,因为如果我已经登录很久以前,但最近它也把我视为非活动用户,因为它看到我在很久以前登录。
所以我想解决上面描述的错误并且还满足第二个条件(选择从未登录过的人)。
首先,您的查询需要包含所有用户,因此将其转换为LEFT JOIN。
接下来,您的查询需要使用GROUP BY来获取每个用户的MAX登录时间。
第三,不要对列添加日期函数 - 它不会对性能有帮助,而是索引日期列并构造要测试的日期。
SELECT u.id, u.last_name, u.first_name, u.email, u.username
FROM users u
LEFT JOIN login_logs l ON l.user_id = u.id
WHERE u.activated = 1 AND u.suspended = 0
GROUP BY u.id, u.last_name, u.first_name, u.email, u.username
HAVING IFNULL(max(l.login_datetime), 0) <= ADDDATE(CURDATE(), interval -90 day)
ORDER BY u.last_name, u.first_name, u.id
IFNULL(max(l.login_datetime), 0)
的最后一部分确保如果LEFT JOIN导致login_logs中没有记录(从未登录),它将使用日期0进行测试,这显然是<= 90 days ago
; 因此记录(用户)显示。
select u.* from user u left outer join login l
on u.id = l.user_id
where l.user_id is null
or DATEDIFF(CURDATE(), l.login_datetime) <= 90
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.