Mysql 根据加入 table 日志的用户 ID 获取第二个最大日期限制 1
Mysql get second max date limit 1 base on user id joining table log
我想从 user_log table 获取第二个最大登录日期,并在 user_id
记录不在 user_log
中时将登录日期返回到 null
table 并且只有一次登录日期 user_log
table.
示例案例。
user_log 案例 1
╔═════════╦═══════════╦═══════╦══════════════════════╗
║ ID ║ USER_ID ║ TYPE ║ UPDATED_AT ║
╠═════════╬═══════════╬═══════╬══════════════════════╣
║ 1 ║ 1 ║ Login ║ 2019-06-19 15:00:00 ║
║ 2 ║ 2 ║ Login ║ 2019-06-19 15:02:00 ║last login user_id 2
║ 3 ║ 1 ║ Logout║ 2019-06-19 15:03:00 ║
║ 5 ║ 1 ║ Login ║ 2019-06-19 15:04:00 ║last login user_id 1
║ 6 ║ 2 ║ Logout║ 2019-06-19 15:05:00 ║
║ 7 ║ 3 ║ Login ║ 2019-06-19 15:06:00 ║last login user_id 3
║ 8 ║ 2 ║ Login ║ 2019-06-19 15:07:00 ║
║ 9 ║ 1 ║ Logout║ 2019-06-19 15:08:00 ║
║ 10 ║ 1 ║ Login ║ 2019-06-19 15:10:00 ║
║ 11 ║ 3 ║ Logout║ 2019-06-19 15:15:00 ║
║ 12 ║ 3 ║ Login ║ 2019-06-19 15:18:00 ║
╚═════════╩═══════════╩═══════╩══════════════════════╝
user_log 案例 2
╔═════════╦═══════════╦═══════╦══════════════════════╗
║ ID ║ USER_ID ║ TYPE ║ UPDATED_AT ║
╠═════════╬═══════════╬═══════╬══════════════════════╣
║ 1 ║ 1 ║ Login ║ 2019-06-19 15:00:00 ║last login user_id 1
║ 2 ║ 1 ║ Logout║ 2019-06-19 15:03:00 ║
║ 3 ║ 1 ║ Login ║ 2019-06-19 15:04:00 ║
║ 4 ║ 2 ║ Login ║ 2019-06-19 15:05:00 ║
║ 5 ║ 3 ║ Login ║ 2019-06-19 15:07:00 ║
╚═════════╩═══════════╩═══════╩══════════════════════╝
user_log 案例 3
╔═════════╦═══════════╦═══════╦══════════════════════╗
║ ID ║ USER_ID ║ TYPE ║ UPDATED_AT ║
╠═════════╬═══════════╬═══════╬══════════════════════╣
║ 1 ║ 1 ║ Login ║ 2019-06-19 15:00:00 ║
║ 2 ║ 2 ║ Login ║ 2019-06-19 15:05:00 ║
╚═════════╩═══════════╩═══════╩══════════════════════╝
table 用户
╔═════════╦════════════╗
║ ID ║ USERNAME ║
╠═════════╬════════════╣
║ 1 ║ XX ║
║ 2 ║ YY ║
║ 3 ║ ZZ ║
╚═════════╩════════════╝
这是我的查询。
SELECT u.id as iduser,u.username,ul.type,MAX(ul.updated_at) last_login_date
FROM users u
LEFT JOIN user_log ul ON u.id=ul.user_id
where ul.type = 'Login'
GROUP BY u.id
此查询仅显示最大登录日期,并且仅当 user_id
记录在 user_log
table
时
案例 1 的预期结果
╔═══════════╦═══════════╦═══════╦══════════════════════╗
║ USER_ID ║ USERNAME ║ TYPE ║ LAST_LOGIN_DATE ║
╠═══════════╬═══════════╬═══════╬══════════════════════╣
║ 1 ║ XX ║ Login ║ 2019-06-19 15:04:00 ║LOG_ID(5)
║ 2 ║ YY ║ Login ║ 2019-06-19 15:02:00 ║LOG_ID(2)
║ 3 ║ ZZ ║ Login ║ 2019-06-19 15:06:00 ║LOG_ID(7)
╚═══════════╩═══════════╩═══════╩══════════════════════╝
预期结果案例 2
╔═══════════╦═══════════╦═══════╦══════════════════════╗
║ IDUSER ║ USERNAME ║ TYPE ║ LAST_LOGIN_DATE ║
╠═══════════╬═══════════╬═══════╬══════════════════════╣
║ 1 ║ XX ║ Login ║ 2019-06-19 15:00:00 ║LOG_ID(1)
║ 2 ║ YY ║ - ║ - ║LOG_ID(-)
║ 3 ║ ZZ ║ - ║ - ║LOG_ID(-)
╚═══════════╩═══════════╩═══════╩══════════════════════╝
案例 3 的预期结果
╔═══════════╦═══════════╦═══════╦══════════════════════╗
║ USER_ID ║ USERNAME ║ TYPE ║ LAST_LOGIN_DATE ║
╠═══════════╬═══════════╬═══════╬══════════════════════╣
║ 1 ║ XX ║ - ║ - ║LOG_ID(-)
║ 2 ║ YY ║ - ║ - ║LOG_ID(-)
║ 3 ║ ZZ ║ - ║ - ║LOG_ID(-)
╚═══════════╩═══════════╩═══════╩══════════════════════╝
所有情况都应该是一个查询。
SELECT DISTINCT date FROM tbl_date ORDER BY date DESC LIMIT 1,1;
您可以使用此查询获取第二个最大日期。
假设我们有以下三个用户的日志条目:
+----+---------+--------+---------------------+
| id | user_id | type | updated_at |
+----+---------+--------+---------------------+
| 1 | 1 | Login | 2019-06-19 15:00:00 |
| 6 | 2 | Login | 2019-06-19 15:02:00 |
| 2 | 1 | Logout | 2019-06-19 15:03:00 |
| 3 | 1 | Login | 2019-06-19 15:04:00 |
| 7 | 2 | Logout | 2019-06-19 15:05:00 |
| 8 | 2 | Login | 2019-06-19 15:07:00 |
| 4 | 1 | Logout | 2019-06-19 15:08:00 |
| 10 | 3 | Login | 2019-06-19 15:09:00 |
| 5 | 1 | Login | 2019-06-19 15:10:00 |
+----+---------+--------+---------------------+
基于像 What is the simplest SQL Query to find the second largest value? or Get the second highest value in a MySQL table 这样的类似问题,您可以首先创建一个 SELECT
查询,其中 returns 最后一个 login
条目,这将是当前活动的 session/login:
SELECT
user_id,
MAX(updated_at) as max_updated
FROM
user_log
WHERE
type = 'Login'
GROUP BY
user_id
这会给你以下结果:
+---------+---------------------+
| user_id | max_updated |
+---------+---------------------+
| 1 | 2019-06-19 15:10:00 |
| 2 | 2019-06-19 15:07:00 |
| 3 | 2019-06-19 15:09:00 |
+---------+---------------------+
您在 user_log
table 上再次使用同一用户 ID 加入此结果。
SELECT
a.user_id,
a.type,
a.updated_at,
b.max_updated
FROM
user_log a
LEFT JOIN
(
SELECT
user_id,
MAX(updated_at) as max_updated
FROM
user_log
WHERE
type = 'Login'
GROUP BY
user_id
) b ON a.user_id = b.user_id
这会得到以下结果:
+---------+--------+---------------------+---------------------+
| user_id | type | updated_at | max_updated |
+---------+--------+---------------------+---------------------+
| 1 | Login | 2019-06-19 15:00:00 | 2019-06-19 15:10:00 |
| 1 | Logout | 2019-06-19 15:03:00 | 2019-06-19 15:10:00 |
| 1 | Login | 2019-06-19 15:04:00 | 2019-06-19 15:10:00 |
| 1 | Logout | 2019-06-19 15:08:00 | 2019-06-19 15:10:00 |
| 1 | Login | 2019-06-19 15:10:00 | 2019-06-19 15:10:00 |
| 2 | Login | 2019-06-19 15:02:00 | 2019-06-19 15:07:00 |
| 2 | Logout | 2019-06-19 15:05:00 | 2019-06-19 15:07:00 |
| 2 | Login | 2019-06-19 15:07:00 | 2019-06-19 15:07:00 |
| 3 | Login | 2019-06-19 15:09:00 | 2019-06-19 15:09:00 |
+---------+--------+---------------------+---------------------+
您可以使用 max_updated
列删除 updated_at
列相同的任何行。这样的行将是 "last" 行,但由于您不想要这些行(而是之前的所有行),您可以使用 WHERE
子句过滤它们(并通过 type
。
SELECT
a.user_id,
a.type,
a.updated_at,
b.max_updated
FROM
user_log a
LEFT JOIN
(
SELECT
user_id,
MAX(updated_at) as max_updated
FROM
user_log
WHERE
type = 'Login'
GROUP BY
user_id
) b ON a.user_id = b.user_id
WHERE
a.updated_at != b.max_updated AND
type = 'Login'
这将为您提供以下内容:
+---------+-------+---------------------+---------------------+
| user_id | type | updated_at | max_updated |
+---------+-------+---------------------+---------------------+
| 1 | Login | 2019-06-19 15:00:00 | 2019-06-19 15:10:00 |
| 1 | Login | 2019-06-19 15:04:00 | 2019-06-19 15:10:00 |
| 2 | Login | 2019-06-19 15:02:00 | 2019-06-19 15:07:00 |
+---------+-------+---------------------+---------------------+
这看起来很有希望,因为用户 3
的行不再存在,我们只有 Login
个条目并且未选择来自 current/active 会话的登录。从这里开始,通过对用户 table.
使用 GROUP BY
然后使用 LEFT JOIN
就很简单了
SELECT
u.id,
u.username,
l.type,
l.last_login_date
FROM
users u
LEFT JOIN
(
SELECT
a.user_id,
a.type,
MAX(a.updated_at) AS last_login_date
FROM
user_log a
LEFT JOIN
(
SELECT
user_id,
MAX(updated_at) as max_updated
FROM
user_log
WHERE
type = 'Login'
GROUP BY
user_id
) b ON a.user_id = b.user_id
WHERE
a.updated_at != b.max_updated AND
type = 'Login'
GROUP BY
a.user_id) l ON u.id = l.user_id
这会得到以下结果:
+------+----------+-------+---------------------+
| id | username | type | last_login_date |
+------+----------+-------+---------------------+
| 1 | XX | Login | 2019-06-19 15:04:00 |
| 2 | YY | Login | 2019-06-19 15:02:00 |
| 3 | ZZ | NULL | NULL |
+------+----------+-------+---------------------+
我想从 user_log table 获取第二个最大登录日期,并在 user_id
记录不在 user_log
中时将登录日期返回到 null
table 并且只有一次登录日期 user_log
table.
示例案例。
user_log 案例 1
╔═════════╦═══════════╦═══════╦══════════════════════╗
║ ID ║ USER_ID ║ TYPE ║ UPDATED_AT ║
╠═════════╬═══════════╬═══════╬══════════════════════╣
║ 1 ║ 1 ║ Login ║ 2019-06-19 15:00:00 ║
║ 2 ║ 2 ║ Login ║ 2019-06-19 15:02:00 ║last login user_id 2
║ 3 ║ 1 ║ Logout║ 2019-06-19 15:03:00 ║
║ 5 ║ 1 ║ Login ║ 2019-06-19 15:04:00 ║last login user_id 1
║ 6 ║ 2 ║ Logout║ 2019-06-19 15:05:00 ║
║ 7 ║ 3 ║ Login ║ 2019-06-19 15:06:00 ║last login user_id 3
║ 8 ║ 2 ║ Login ║ 2019-06-19 15:07:00 ║
║ 9 ║ 1 ║ Logout║ 2019-06-19 15:08:00 ║
║ 10 ║ 1 ║ Login ║ 2019-06-19 15:10:00 ║
║ 11 ║ 3 ║ Logout║ 2019-06-19 15:15:00 ║
║ 12 ║ 3 ║ Login ║ 2019-06-19 15:18:00 ║
╚═════════╩═══════════╩═══════╩══════════════════════╝
user_log 案例 2
╔═════════╦═══════════╦═══════╦══════════════════════╗
║ ID ║ USER_ID ║ TYPE ║ UPDATED_AT ║
╠═════════╬═══════════╬═══════╬══════════════════════╣
║ 1 ║ 1 ║ Login ║ 2019-06-19 15:00:00 ║last login user_id 1
║ 2 ║ 1 ║ Logout║ 2019-06-19 15:03:00 ║
║ 3 ║ 1 ║ Login ║ 2019-06-19 15:04:00 ║
║ 4 ║ 2 ║ Login ║ 2019-06-19 15:05:00 ║
║ 5 ║ 3 ║ Login ║ 2019-06-19 15:07:00 ║
╚═════════╩═══════════╩═══════╩══════════════════════╝
user_log 案例 3
╔═════════╦═══════════╦═══════╦══════════════════════╗
║ ID ║ USER_ID ║ TYPE ║ UPDATED_AT ║
╠═════════╬═══════════╬═══════╬══════════════════════╣
║ 1 ║ 1 ║ Login ║ 2019-06-19 15:00:00 ║
║ 2 ║ 2 ║ Login ║ 2019-06-19 15:05:00 ║
╚═════════╩═══════════╩═══════╩══════════════════════╝
table 用户
╔═════════╦════════════╗
║ ID ║ USERNAME ║
╠═════════╬════════════╣
║ 1 ║ XX ║
║ 2 ║ YY ║
║ 3 ║ ZZ ║
╚═════════╩════════════╝
这是我的查询。
SELECT u.id as iduser,u.username,ul.type,MAX(ul.updated_at) last_login_date
FROM users u
LEFT JOIN user_log ul ON u.id=ul.user_id
where ul.type = 'Login'
GROUP BY u.id
此查询仅显示最大登录日期,并且仅当 user_id
记录在 user_log
table
案例 1 的预期结果
╔═══════════╦═══════════╦═══════╦══════════════════════╗
║ USER_ID ║ USERNAME ║ TYPE ║ LAST_LOGIN_DATE ║
╠═══════════╬═══════════╬═══════╬══════════════════════╣
║ 1 ║ XX ║ Login ║ 2019-06-19 15:04:00 ║LOG_ID(5)
║ 2 ║ YY ║ Login ║ 2019-06-19 15:02:00 ║LOG_ID(2)
║ 3 ║ ZZ ║ Login ║ 2019-06-19 15:06:00 ║LOG_ID(7)
╚═══════════╩═══════════╩═══════╩══════════════════════╝
预期结果案例 2
╔═══════════╦═══════════╦═══════╦══════════════════════╗
║ IDUSER ║ USERNAME ║ TYPE ║ LAST_LOGIN_DATE ║
╠═══════════╬═══════════╬═══════╬══════════════════════╣
║ 1 ║ XX ║ Login ║ 2019-06-19 15:00:00 ║LOG_ID(1)
║ 2 ║ YY ║ - ║ - ║LOG_ID(-)
║ 3 ║ ZZ ║ - ║ - ║LOG_ID(-)
╚═══════════╩═══════════╩═══════╩══════════════════════╝
案例 3 的预期结果
╔═══════════╦═══════════╦═══════╦══════════════════════╗
║ USER_ID ║ USERNAME ║ TYPE ║ LAST_LOGIN_DATE ║
╠═══════════╬═══════════╬═══════╬══════════════════════╣
║ 1 ║ XX ║ - ║ - ║LOG_ID(-)
║ 2 ║ YY ║ - ║ - ║LOG_ID(-)
║ 3 ║ ZZ ║ - ║ - ║LOG_ID(-)
╚═══════════╩═══════════╩═══════╩══════════════════════╝
所有情况都应该是一个查询。
SELECT DISTINCT date FROM tbl_date ORDER BY date DESC LIMIT 1,1;
您可以使用此查询获取第二个最大日期。
假设我们有以下三个用户的日志条目:
+----+---------+--------+---------------------+
| id | user_id | type | updated_at |
+----+---------+--------+---------------------+
| 1 | 1 | Login | 2019-06-19 15:00:00 |
| 6 | 2 | Login | 2019-06-19 15:02:00 |
| 2 | 1 | Logout | 2019-06-19 15:03:00 |
| 3 | 1 | Login | 2019-06-19 15:04:00 |
| 7 | 2 | Logout | 2019-06-19 15:05:00 |
| 8 | 2 | Login | 2019-06-19 15:07:00 |
| 4 | 1 | Logout | 2019-06-19 15:08:00 |
| 10 | 3 | Login | 2019-06-19 15:09:00 |
| 5 | 1 | Login | 2019-06-19 15:10:00 |
+----+---------+--------+---------------------+
基于像 What is the simplest SQL Query to find the second largest value? or Get the second highest value in a MySQL table 这样的类似问题,您可以首先创建一个 SELECT
查询,其中 returns 最后一个 login
条目,这将是当前活动的 session/login:
SELECT
user_id,
MAX(updated_at) as max_updated
FROM
user_log
WHERE
type = 'Login'
GROUP BY
user_id
这会给你以下结果:
+---------+---------------------+
| user_id | max_updated |
+---------+---------------------+
| 1 | 2019-06-19 15:10:00 |
| 2 | 2019-06-19 15:07:00 |
| 3 | 2019-06-19 15:09:00 |
+---------+---------------------+
您在 user_log
table 上再次使用同一用户 ID 加入此结果。
SELECT
a.user_id,
a.type,
a.updated_at,
b.max_updated
FROM
user_log a
LEFT JOIN
(
SELECT
user_id,
MAX(updated_at) as max_updated
FROM
user_log
WHERE
type = 'Login'
GROUP BY
user_id
) b ON a.user_id = b.user_id
这会得到以下结果:
+---------+--------+---------------------+---------------------+
| user_id | type | updated_at | max_updated |
+---------+--------+---------------------+---------------------+
| 1 | Login | 2019-06-19 15:00:00 | 2019-06-19 15:10:00 |
| 1 | Logout | 2019-06-19 15:03:00 | 2019-06-19 15:10:00 |
| 1 | Login | 2019-06-19 15:04:00 | 2019-06-19 15:10:00 |
| 1 | Logout | 2019-06-19 15:08:00 | 2019-06-19 15:10:00 |
| 1 | Login | 2019-06-19 15:10:00 | 2019-06-19 15:10:00 |
| 2 | Login | 2019-06-19 15:02:00 | 2019-06-19 15:07:00 |
| 2 | Logout | 2019-06-19 15:05:00 | 2019-06-19 15:07:00 |
| 2 | Login | 2019-06-19 15:07:00 | 2019-06-19 15:07:00 |
| 3 | Login | 2019-06-19 15:09:00 | 2019-06-19 15:09:00 |
+---------+--------+---------------------+---------------------+
您可以使用 max_updated
列删除 updated_at
列相同的任何行。这样的行将是 "last" 行,但由于您不想要这些行(而是之前的所有行),您可以使用 WHERE
子句过滤它们(并通过 type
。
SELECT
a.user_id,
a.type,
a.updated_at,
b.max_updated
FROM
user_log a
LEFT JOIN
(
SELECT
user_id,
MAX(updated_at) as max_updated
FROM
user_log
WHERE
type = 'Login'
GROUP BY
user_id
) b ON a.user_id = b.user_id
WHERE
a.updated_at != b.max_updated AND
type = 'Login'
这将为您提供以下内容:
+---------+-------+---------------------+---------------------+
| user_id | type | updated_at | max_updated |
+---------+-------+---------------------+---------------------+
| 1 | Login | 2019-06-19 15:00:00 | 2019-06-19 15:10:00 |
| 1 | Login | 2019-06-19 15:04:00 | 2019-06-19 15:10:00 |
| 2 | Login | 2019-06-19 15:02:00 | 2019-06-19 15:07:00 |
+---------+-------+---------------------+---------------------+
这看起来很有希望,因为用户 3
的行不再存在,我们只有 Login
个条目并且未选择来自 current/active 会话的登录。从这里开始,通过对用户 table.
GROUP BY
然后使用 LEFT JOIN
就很简单了
SELECT
u.id,
u.username,
l.type,
l.last_login_date
FROM
users u
LEFT JOIN
(
SELECT
a.user_id,
a.type,
MAX(a.updated_at) AS last_login_date
FROM
user_log a
LEFT JOIN
(
SELECT
user_id,
MAX(updated_at) as max_updated
FROM
user_log
WHERE
type = 'Login'
GROUP BY
user_id
) b ON a.user_id = b.user_id
WHERE
a.updated_at != b.max_updated AND
type = 'Login'
GROUP BY
a.user_id) l ON u.id = l.user_id
这会得到以下结果:
+------+----------+-------+---------------------+
| id | username | type | last_login_date |
+------+----------+-------+---------------------+
| 1 | XX | Login | 2019-06-19 15:04:00 |
| 2 | YY | Login | 2019-06-19 15:02:00 |
| 3 | ZZ | NULL | NULL |
+------+----------+-------+---------------------+