选择所有非活动用户的SQL查询

mat*_*hew 3 mysql sql

我有一个查询要实现.

我有2个表:userlogin_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
Run Code Online (Sandbox Code Playgroud)

以上查询不正确,因为如果我已经登录很久以前,但最近它也把我视为非活动用户,因为它看到我在很久以前登录.

所以我想解决上面描述的错误并且还满足第二个条件(选择从未登录过的人).

Ric*_*iwi 7

首先,您的查询需要包含所有用户,因此将其转换为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
Run Code Online (Sandbox Code Playgroud)

那里的最后一部分IFNULL(max(l.login_datetime), 0)确保如果LEFT JOIN导致login_logs中没有记录(从未登录),它将使用日期0进行测试,这显然是<= 90 days ago; 因此记录(用户)显示.