Как сгруппировать записи по последним дубликатам в MySQL? - PullRequest
0 голосов
/ 12 мая 2019

У меня есть таблица, в которой хранится информация о логинах пользователей. Я хочу сгруппировать последние дубликаты записей. Например:

+---+------------+-------------+-------------+------------------+
|   |     ip     |   platform  |   browser   |       date       |
+---+------------+-------------+-------------+------------------+
| 1 | 127.0.0.1  |   Windows   |   Chrome    | 2018-01-01 00:00 |
| 2 | 127.0.0.1  |   Windows   |   Chrome    | 2018-01-02 00:00 |
| 3 | 10.0.0.1   |   Linux     |   Firefox   | 2018-01-03 00:00 |
| 4 | 127.0.0.1  |   Windows   |   Chrome    | 2018-01-04 00:00 |
+---+------------+-------------+-------------+------------------+

Будет выводить:

+-----+------------+-------------+-------------+-------------+
|     |     ip     |   platform  |   browser   | num_records |
+-----+------------+-------------+-------------+-------------+
| 1-2 | 127.0.0.1  |   Windows   |   Chrome    |      2      |
| 3   | 10.0.0.1   |   Linux     |   Firefox   |      1      |
| 4   | 127.0.0.1  |   Windows   |   Chrome    |      1      |
+-----+------------+-------------+-------------+-------------+

(для простоты я отправил дату, должен быть диапазон дат, такой как id)

Обратите внимание, что идентификаторы 1,2,4 одинаковы, но 1,2 и 4 сгруппированы отдельно из-за временной шкалы (есть другая запись, которая разделяет их).

Чтобы найти дубликаты, я должен рассмотреть следующие столбцы: ip, platform, browser. Если что-то отличается от этих столбцов, то это не дубликат.

Я могу сделать:

SELECT      ip, platform, browser, COUNT(1) AS num_records
FROM        users_logins
WHERE       user_id = 1
GROUP BY    ip, platform, browser

Но это сгруппирует все записи без учета временной шкалы.

1 Ответ

2 голосов
/ 12 мая 2019

Это проблема пробелов и островков.В MySQL 8+ вы можете использовать разницу номеров строк:

select ip, platform, browser,
       count(*) as numrecords,
       min(id), max(id),
       min(date), max(date)
from (select t.*,
             row_number() over (order by date) as seqnum,
             row_number() over (partition by ip, platform, browser order by date) as seqnum_2
      from t
     ) t
group by ip, platform, browser, (seqnum - seqnum_2)
order by min(date) desc;
...