У меня есть некоторые трудности с командами mySQL, которые я хочу выполнить.
SELECT a.timestamp, name, count(b.name)
FROM time a, id b
WHERE a.user = b.user
AND a.id = b.id
AND b.name = 'John'
AND a.timestamp BETWEEN '2010-11-16 10:30:00' AND '2010-11-16 11:00:00'
GROUP BY a.timestamp
Это мой текущий вывод.
timestamp name count(b.name)
------------------- ---- -------------
2010-11-16 10:32:22 John 2
2010-11-16 10:35:12 John 7
2010-11-16 10:36:34 John 1
2010-11-16 10:37:45 John 2
2010-11-16 10:48:26 John 8
2010-11-16 10:55:00 John 9
2010-11-16 10:58:08 John 2
Как мне сгруппировать их в результаты с 5-минутным интервалом?
Я хочу, чтобы мой результат был похож на
timestamp name count(b.name)
------------------- ---- -------------
2010-11-16 10:30:00 John 2
2010-11-16 10:35:00 John 10
2010-11-16 10:40:00 John 0
2010-11-16 10:45:00 John 8
2010-11-16 10:50:00 John 0
2010-11-16 10:55:00 John 11
Ответы:
Это работает с каждым интервалом.
PostgreSQL
SELECT TIMESTAMP WITH TIME ZONE 'epoch' + INTERVAL '1 second' * round(extract('epoch' from timestamp) / 300) * 300 as timestamp, name, count(b.name) FROM time a, id WHERE … GROUP BY round(extract('epoch' from timestamp) / 300), name
MySQL
SELECT timestamp, -- not sure about that name, count(b.name) FROM time a, id WHERE … GROUP BY UNIX_TIMESTAMP(timestamp) DIV 300, name
источник
Я столкнулся с той же проблемой.
Я обнаружил, что легко сгруппировать по любому минутному интервалу, просто разделив эпоху на минуты в количестве секунд, а затем либо округляя, либо используя пол, чтобы получить остаток. Итак, если вы хотите получить интервал в 5 минут, вы должны использовать 300 секунд .
SELECT COUNT(*) cnt, to_timestamp(floor((extract('epoch' from timestamp_column) / 300 )) * 300) AT TIME ZONE 'UTC' as interval_alias FROM TABLE_NAME GROUP BY interval_alias
interval_alias cnt ------------------- ---- 2010-11-16 10:30:00 2 2010-11-16 10:35:00 10 2010-11-16 10:45:00 8 2010-11-16 10:55:00 11
Это вернет данные, правильно сгруппированные по выбранному интервалу минут; однако он не вернет интервалы, которые не содержат никаких данных. Чтобы получить эти пустые интервалы, мы можем использовать функцию generate_series .
SELECT generate_series(MIN(date_trunc('hour',timestamp_column)), max(date_trunc('minute',timestamp_column)),'5m') as interval_alias FROM TABLE_NAME
Результат:
interval_alias ------------------- 2010-11-16 10:30:00 2010-11-16 10:35:00 2010-11-16 10:40:00 2010-11-16 10:45:00 2010-11-16 10:50:00 2010-11-16 10:55:00
Теперь, чтобы получить результат с интервалом с нулевыми вхождениями, мы просто объединяем оба набора результатов .
SELECT series.minute as interval, coalesce(cnt.amnt,0) as count from ( SELECT count(*) amnt, to_timestamp(floor((extract('epoch' from timestamp_column) / 300 )) * 300) AT TIME ZONE 'UTC' as interval_alias from TABLE_NAME group by interval_alias ) cnt RIGHT JOIN ( SELECT generate_series(min(date_trunc('hour',timestamp_column)), max(date_trunc('minute',timestamp_column)),'5m') as minute from TABLE_NAME ) series on series.minute = cnt.interval_alias
Конечный результат будет включать серии со всеми 5-минутными интервалами, даже те, которые не имеют значений.
interval count ------------------- ---- 2010-11-16 10:30:00 2 2010-11-16 10:35:00 10 2010-11-16 10:40:00 0 2010-11-16 10:45:00 8 2010-11-16 10:50:00 0 2010-11-16 10:55:00 11
Интервал можно легко изменить, настроив последний параметр generate_series. В нашем случае мы используем «5 минут», но это может быть любой интервал, который мы хотим.
источник
Лучше использовать
GROUP BY UNIX_TIMESTAMP(time_stamp) DIV 300
вместо округления (../ 300) из-за округления, которое я обнаружил, что некоторые записи подсчитываются в двух сгруппированных наборах результатов.источник
DIV
в MySQL естьfloor()
деление с плавающей запятой, безопасное сBIGINT
s.Для postgres мне было проще и точнее использовать
date_trunc
функция, например:
select name, sum(count), date_trunc('minute',timestamp) as timestamp FROM table WHERE xxx GROUP BY name,date_trunc('minute',timestamp) ORDER BY timestamp
Вы можете указать для date_trunc различные разрешения, такие как «минута», «час», «день» и т. Д.
источник
5
здесь установить интервал 5 минут?Запрос будет примерно таким:
SELECT DATE_FORMAT( MIN(timestamp), '%d/%m/%Y %H:%i:00' ) AS tmstamp, name, COUNT(id) AS cnt FROM table GROUP BY ROUND(UNIX_TIMESTAMP(timestamp) / 300), name
источник
Вероятно, вам придется разбить свою метку времени на ymd: HM и использовать DIV 5, чтобы разделить минуты на 5-минутные ячейки - что-то вроде
select year(a.timestamp), month(a.timestamp), hour(a.timestamp), minute(a.timestamp) DIV 5, name, count(b.name) FROM time a, id b WHERE a.user = b.user AND a.id = b.id AND b.name = 'John' AND a.timestamp BETWEEN '2010-11-16 10:30:00' AND '2010-11-16 11:00:00' GROUP BY year(a.timestamp), month(a.timestamp), hour(a.timestamp), minute(a.timestamp) DIV 12
... а затем преобразовать вывод в клиентский код, чтобы он выглядел так, как вам нравится. Или вы можете построить всю строку даты, используя оператор sql concat вместо получения отдельных столбцов, если хотите.
select concat(year(a.timestamp), "-", month(a.timestamp), "-" ,day(a.timestamp), " " , lpad(hour(a.timestamp),2,'0'), ":", lpad((minute(a.timestamp) DIV 5) * 5, 2, '0'))
... а затем сгруппируйтесь по этому
источник
Не уверен, что он вам еще нужен.
SELECT FROM_UNIXTIME(FLOOR((UNIX_TIMESTAMP(timestamp))/300)*300) AS t,timestamp,count(1) as c from users GROUP BY t ORDER BY t;
источник
Как насчет этого:
select from_unixtime(unix_timestamp(timestamp) - unix_timestamp(timestamp) mod 300) as ts, sum(value) from group_interval group by ts order by ts ;
источник
Я обнаружил, что с MySQL, вероятно, правильный запрос будет следующим:
SELECT SUBSTRING( FROM_UNIXTIME( CEILING( timestamp /300 ) *300, '%Y-%m-%d %H:%i:%S' ) , 1, 19 ) AS ts_CEILING, SUM(value) FROM group_interval GROUP BY SUBSTRING( FROM_UNIXTIME( CEILING( timestamp /300 ) *300, '%Y-%m-%d %H:%i:%S' ) , 1, 19 ) ORDER BY SUBSTRING( FROM_UNIXTIME( CEILING( timestamp /300 ) *300, '%Y-%m-%d %H:%i:%S' ) , 1, 19 ) DESC
Дайте мне знать, что вы думаете.
источник
select CONCAT(CAST(CREATEDATE AS DATE),' ',datepart(hour,createdate),':',ROUNd(CAST((CAST((CAST(DATEPART(MINUTE,CREATEDATE) AS DECIMAL (18,4)))/5 AS INT)) AS DECIMAL (18,4))/12*60,2)) AS '5MINDATE' ,count(something) from TABLE group by CONCAT(CAST(CREATEDATE AS DATE),' ',datepart(hour,createdate),':',ROUNd(CAST((CAST((CAST(DATEPART(MINUTE,CREATEDATE) AS DECIMAL (18,4)))/5 AS INT)) AS DECIMAL (18,4))/12*60,2))
источник