как посчитать таймдифф для каждого пользователя mysql - PullRequest
0 голосов
/ 06 марта 2020

допустим, у меня есть таблица данных, подобная этой

ID  users_Id   createdAt
1   12         '2020-01-01'
2   12         '2020-01-03'
3   12         '2020-01-06'
4   13         '2020-01-02'
5   13         '2020-01-03'  

как мне получить временную разницу для каждой транзакции и каждого пользователя, чтобы результаты были такими же, как это объяснение

MAX   MIN   AVERAGE    MEDIAN
3     1     3          3 

:

  • максимальное значение timediff имеет место в users_id 12, когда '2020-01-03' до '2020-01-06' (3 дня)
  • минимальное значение timediff происходит в users_id 13, когда транзакция между '2020-01-02' и '2020-01-03'
  • в среднем составляет 3 (2 дня в users_Id 12 + 3 дня в users_Id 12 + 1 дней в users_Id 13) / количество user_id (12 и 13)

Ответы [ 2 ]

2 голосов
/ 06 марта 2020

Вы можете использовать что-то вроде этого ( без вычисления медианы ):

SELECT MIN(diff) AS `MIN`, MAX(diff) AS `MAX`, SUM(diff) / COUNT(DISTINCT user_id) AS `AVG`
FROM (
  SELECT ID, user_id, DATEDIFF((SELECT t2.createdAt FROM test t2 WHERE t2.user_id = t1.user_id AND t1.createdAt <= t2.createdAt AND t2.id <> t1.id LIMIT 1), t1.createdAt) AS diff
  FROM test t1
  WHERE order_status_id in (4, 5, 6, 8)
) DiffTable
WHERE diff IS NOT NULL

Медиана гораздо сложнее вычислить на MySQL. Но вы можете использовать что-то вроде этого на основе этого ответа на StackOverflow . Как видите, запрос становится очень грязным. Нет такой функции, как SUM или AVG на MySQL для получения медианы.

SELECT MIN(DiffTable.diff) AS `MIN`, MAX(DiffTable.diff) AS `MAX`, SUM(DiffTable.diff) / COUNT(DISTINCT user_id) AS `AVG`, MIN(median.diff) AS `MEDIAN`
FROM (
  SELECT ID, user_id, DATEDIFF((SELECT t2.createdAt FROM test t2 WHERE t2.user_id = t1.user_id AND t1.createdAt <= t2.createdAt AND t2.id <> t1.id LIMIT 1), t1.createdAt) AS diff
  FROM test t1
  WHERE order_status_id in (4, 5, 6, 8)
) DiffTable, (
  SELECT m1.diff FROM (
    SELECT ID, user_id, DATEDIFF((SELECT t2.createdAt FROM test t2 WHERE t2.user_id = t1.user_id AND t1.createdAt <= t2.createdAt AND t2.id <> t1.id LIMIT 1), t1.createdAt) AS diff
    FROM test t1
    WHERE order_status_id in (4, 5, 6, 8)
  ) m1, (
    SELECT ID, user_id, DATEDIFF((SELECT t2.createdAt FROM test t2 WHERE t2.user_id = t1.user_id AND t1.createdAt <= t2.createdAt AND t2.id <> t1.id LIMIT 1), t1.createdAt) AS diff
    FROM test t1
    WHERE order_status_id in (4, 5, 6, 8)
  ) m2
  WHERE m1.diff IS NOT NULL AND m2.diff IS NOT NULL
  GROUP BY m1.diff
  HAVING SUM(SIGN(1-SIGN(m1.diff-m2.diff))) = (COUNT(*)+1)/2
) median
WHERE DiffTable.diff IS NOT NULL

демо на dbfiddle.uk

1 голос
/ 06 марта 2020

В MySQL <5.7 я бы использовал коррелированный подзапрос для восстановления последнего <code>created_at того же пользователя. Это дает вам все столбцы, которые, как вы ожидаете, за исключением медианы:

select
    max(diff) max_diff,
    min(diff) min_diff,
    avg(diff) avg_diff
from (
    select
        t.*,
        datediff(
            created_at, 
            (select max(t1.created_at) from mytable t1 where t1.user_id = t.user_id and t1.created_at < t.created_at) 
        ) diff
    from mytable t
) t
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...