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                |
+------+----------+-------+---------------------+