Mysql получить второй максимальный предел даты 1 на основе идентификатора пользователя, присоединяющегося к журналу таблицы - PullRequest
1 голос
/ 20 июня 2019

Я хочу получить вторую максимальную дату входа в систему из таблицы user_log и вернуть дату входа в систему null, когда записи user_id находятся не в таблице user_log, а только в одной дате входа в таблицу user_log.

для примера.

user_log CASE 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 CASE 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 CASE 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  ║
╚═════════╩═══════════╩═══════╩══════════════════════╝

пользователи таблиц

╔═════════╦════════════╗
║ 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 таблице

Ожидаемый результат case 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)
╚═══════════╩═══════════╩═══════╩══════════════════════╝

Ожидаемый результат case 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(-)
╚═══════════╩═══════════╩═══════╩══════════════════════╝

Ожидаемый результат case 3

╔═══════════╦═══════════╦═══════╦══════════════════════╗
║ USER_ID   ║ USERNAME  ║ TYPE  ║  LAST_LOGIN_DATE     ║
╠═══════════╬═══════════╬═══════╬══════════════════════╣
║ 1         ║ XX        ║ -     ║ -                    ║LOG_ID(-)
║ 2         ║ YY        ║ -     ║ -                    ║LOG_ID(-)
║ 3         ║ ZZ        ║ -     ║ -                    ║LOG_ID(-)
╚═══════════╩═══════════╩═══════╩══════════════════════╝

все регистры должны быть одним запросом.

Ответы [ 2 ]

1 голос
/ 20 июня 2019

Предположим, у нас есть следующие записи журнала для трех пользователей:

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

На основе похожих вопросов, таких как Какой самый простой SQL-запрос для поиска второго по величине значения? или Получив второе по величине значение в таблице MySQL , вы можете сначала создать запрос SELECT, который возвращает последнюю запись 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 с тем же идентификатором пользователя.

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 совпадает.Такой строкой будет «последняя» строка, но, поскольку вам не нужны эти строки (а вместо этого все предыдущие строки), вы фильтруете их с помощью предложения 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 записейи логин из текущего / активного сеанса не выбран.Отсюда все просто, используя 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                |
+------+----------+-------+---------------------+
0 голосов
/ 20 июня 2019

ВЫБРАТЬ DISTINCT дату ОТ tbl_date ЗАКАЗАТЬ по дате DESC LIMIT 1,1;

Вы можете использовать этот запрос для получения второй максимальной даты.

...