MySQL Date разность между двумя строками с агрегатной функцией - PullRequest
0 голосов
/ 23 сентября 2019

У меня есть таблица как

id     client_id          date
1      1001               2008-11-26 00:00:00
2      2001               2008-09-01 00:00:00
3      2001               2008-08-31 00:00:00
4      1001               2007-08-26 00:00:00
5      3001               2003-11-26 00:00:00
6      1001               2003-05-05 00:00:00

Я хочу рассчитать разницу в дате между двумя последовательными строками для одного и того же client_id и выбрать только client_id с разницей в датах больше или равно30 дней

Ответы [ 3 ]

2 голосов
/ 23 сентября 2019

В MySQL <8.0, где оконные функции недоступны, рассмотрим: </p>

SELECT t.*, t1.date next_date, DATEDIFF(t1.date, t.date) date_diff
FROM mytable t
INNER JOIN mytable t1
    ON  t1.client_id = t.client_id
    AND DATEDIFF(t1.date, t.date) >= 30
    AND NOT EXISTS (
        SELECT 1 
        FROM mytable t2
        WHERE 
            t2.client_id = t.client_id 
            AND t2.date > t.date
            AND t2.date < t1.date
    )
ORDER BY t.client_id, t.date

Этот запрос дает вам записи, следующая запись которых для того же клиента - более 30 дней спустя.Он работает путем самостоятельного присоединения к таблице и применения следующих условий:

  • присоединенная запись должна принадлежать одному и тому же клиенту
  • ее дата должна быть как минимум на 30 дней больше датытекущей записи
  • не должно существовать другой записи для того же клиента, чья дата больше, чем дата текущей записи и меньше, чем datea объединенной записи (это реализует концепцию next запись)

Демонстрация на DB Fiddle :

Ваш пример данных (правильно отсортирован):

| id  | client_id | date       |
| --- | --------- | ---------- |
| 6   | 1001      | 2003-05-05 |
| 4   | 1001      | 2007-08-26 |
| 1   | 1001      | 2008-11-26 |
| 3   | 2001      | 2008-08-31 |
| 2   | 2001      | 2008-09-01 |
| 5   | 3001      | 2003-11-26 |

Результаты запроса:

| id  | client_id | date       | next_date  | date_diff |
| --- | --------- | ---------- | ---------- | --------- |
| 4   | 1001      | 2007-08-26 | 2008-11-26 | 458       |
| 6   | 1001      | 2003-05-05 | 2007-08-26 | 1574      |
0 голосов
/ 23 сентября 2019

Мне показалось интересным, что и сделал для вас, поскольку я вижу, что данные фиктивны, а идентификатор больше для старых дат, я игнорирую поле идентификатора

select * from (выберите client_id, maxs, max (all_dt) в сек, datediff (maxs, max (all_dt)) как diff из (выберите * из (выберите client_id, max (dt) в качестве maxs из table_name t group по client_id) mx оставьте соединение (выберите client_id client_id_all, dt как all_dt изимя_таблицы t2) all_ on mx.client_id = all_.client_id_all порядок по mx.client_id) f где all_dt = 30

идентификатор клиента с одной записью даты иразница менее 30 не будет указана в выходных данных.

Надеюсь, это поможет.

Удачи

0 голосов
/ 23 сентября 2019

Вот мое решение.Поскольку версия MySQL не позволяет использовать функцию LEAD ().Для поиска следующей даты я использую запрос SELECT date FROM mytable WHERE client_id = t.client_id AND t.id < id LIMIT 1

SELECT client_id 
FROM (SELECT t.*, (SELECT date FROM mytable WHERE client_id = t.client_id AND t.id < id LIMIT 1) AS lead_date
FROM mytable t) t2 
WHERE ABS(datediff(lead_date, date)) >= 30 GROUP BY client_id
...