MySQL Метка времени групповой эпохи каждые 15 минут - PullRequest
2 голосов
/ 18 июня 2020

У меня есть база данных, которая собирает некоторые данные с довольно высокой частотой и записывает временную метку каждой записи (хранится как время эпохи, а не mysql datetime). Например,

timestamp               rssi    sender
-------------------------------------------
1592353967.171600       -67     9EDA3DBFFE15
1592353967.228000       -67     9EDA3DBFFE15
1592353967.282900       -62     E2ED2569BE2
1592353971.892600       -67     9EDA3DBFFE15
1592353973.962900       -61     2ADE2E4597B2
...

Моя цель - иметь возможность получить количество всех строк за 15-минутные интервалы времени, которые после исследования можно получить с помощью GROUP BY. В идеале окончательный результат должен выглядеть так:

timestamp               count
------------------------------
1592352000 (8:00pm EST)   38    
1592352900 (8:15pm EST)   22
1592353800 (8:30pm EST)   0 <----- Important, must include periods with 0 entries
1592354700 (8:45pm EST)   61
...

У меня здесь в основном проблемы с двумя вещами: 1. Возможность отображать интервалы временных меток в результатах 2. Отображение интервалов с 0 строками внутри период времени

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

 Showing rows 0 - 23 (24 total, Query took 0.0264 seconds.)

SELECT count(*) AS total, MINUTE(FROM_UNIXTIME(timestamp)) AS minute
FROM requests
WHERE timestamp >= 1592352000 AND timestamp < (1592352000 + 3600)  
GROUP BY MINUTE(FROM_UNIXTIME(timestamp))

total   minute  
55  32  
89  33  
64  34  
55  35  
87  36  
82  37  
90  38  
69  39  
74  40  
47  41  
89  42  
53  43  
71  44  
87  45  
72  46  
83  47  
86  48  
83  49  
113 50  
76  51  
77  52  
88  53  
81  54  
28  55  

Эти данные верны, однако есть периоды, которые здесь не отображаются (первые 30 минут этого часа не содержат данных, поэтому первая запись minute начинается с 32). Также пытаюсь получать каждые 15 минут, используя

SELECT count(*) AS total, MINUTE(FROM_UNIXTIME(timestamp)) AS minute
FROM requests
WHERE timestamp >= 1592352000 AND timestamp < (1592352000 + 3600)  
GROUP BY MINUTE(FROM_UNIXTIME(timestamp)) DIV 15

#1055 - Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'wave_master.requests.timestamp' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

Любая помощь будет принята с благодарностью.

1 Ответ

2 голосов
/ 18 июня 2020

Вы можете использовать таблицу «чисел» для генерации 15-минутных периодов в течение часа (0–3), а затем LEFT JOIN для ваших подсчетов, сгруппированных по 15-минутным периодам, используя COALESCE вместо NULL значения с 0:

SELECT periods.period * 900 + 1592352000 AS timestamp,
       FROM_UNIXTIME(periods.period * 900 + 1592352000) AS time,
       COALESCE(counts.total, 0) AS total
FROM (
  SELECT 0 period
  UNION ALL SELECT 1 
  UNION ALL SELECT 2
  UNION ALL SELECT 3
) periods
LEFT JOIN (
  SELECT (timestamp - 1592352000) DIV 900 AS period,
         COUNT(*) AS total
  FROM requests
  WHERE timestamp >= 1592352000 AND timestamp < 1592352000 + 3600
  GROUP BY period
) counts ON counts.period = periods.period

Вывод (для данных в вашем вопросе плюс несколько других значений):

timestamp   time                    total
1592352000  2020-06-17 00:00:00     1
1592352900  2020-06-17 00:15:00     1
1592353800  2020-06-17 00:30:00     5
1592354700  2020-06-17 00:45:00     0

Демо на dbfiddle

...