MySQL запрос рассчитывает удержание пользователя в определенном диапазоне дат - PullRequest
0 голосов
/ 20 декабря 2018

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

+----------+-------------+
| Field    | Type        |
+----------+-------------+
| id       | varchar(17) |
| log_date | date        |
+----------+-------------+

SELECT last_day.log_date, COUNT(distinct last_day.id) as users_num
FROM (SELECT DISTINCT log_date, id
      FROM `userActivity`) this_day
JOIN (SELECT DISTINCT log_date, id
      FROM `userActivity`) last_day
ON this_day.id = last_day.id
AND this_day.log_date = "2018-10-01"
AND last_day.log_date BETWEEN "2018-10-01" AND "2018-10-30"
GROUP BY log_date;

Но проблема, с которой я сталкиваюсь, заключается в том, чтоЯ хочу предположить, что каждый день диапазона дат - это день 0. (аналогично следующему примеру):

Note that the first row is the avg of the below results I need to calculate

Обратите внимание, что первая строкана картинке - среднее из приведенных ниже результатов, которые мне нужно рассчитать.Кто-нибудь знает, как я могу улучшить свой запрос, чтобы получить результат, как на картинке?

1 Ответ

0 голосов
/ 20 декабря 2018

Это решение будет работать только на MySQL 8.x, так как для него требуются CTE (Common Table Expressions):

with digits as (
  select 0 as n union select 1 union select 2 union select 3 union select 4
  union select 5 union select 6 union select 7 union select 8 union select 9
),
series as (
select d1.n * 100 + d2.n * 10 + d3.n as n -- number series from 0 to 999
from digits d1
cross join digits d2
cross join digits d3
)
SELECT last_day.log_date, COUNT(distinct last_day.id) as users_num,
       date_add("2018-10-01", interval s.n day) as current_start
FROM (SELECT DISTINCT log_date, id
      FROM `userActivity`) this_day
JOIN (SELECT DISTINCT log_date, id
      FROM `userActivity`) last_day
ON this_day.id = last_day.id
cross join series s
WHERE s.n <= 30
  AND this_day.log_date = date_add("2018-10-01", interval s.n day)
  AND last_day.log_date BETWEEN date_add("2018-10-01", interval s.n day) 
                            AND date_add("2018-10-30", interval s.n day)
GROUP BY log_date, date_add("2018-10-01", interval s.n day);
...