Saya mengalami kesulitan dengan perintah mySQL yang ingin saya lakukan.
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
Ini adalah pernyataan keluaran saya saat ini.
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
Bagaimana cara mengelompokkan mereka menjadi hasil interval 5 menit?
Saya ingin keluaran saya seperti ini
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
Jawaban:
Ini bekerja dengan setiap interval.
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
sumber
Saya menemukan masalah yang sama.
Saya menemukan bahwa itu adalah mudah untuk kelompok dengan interval menit hanya membagi zaman oleh menit dalam jumlah detik dan kemudian pembulatan atau menggunakan lantai untuk mendapatkan tumpangan dari sisanya. Jadi jika Anda ingin mendapatkan interval dalam 5 menit Anda akan menggunakan 300 detik .
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
Ini akan mengembalikan data dengan benar dikelompokkan dengan interval menit yang dipilih; namun, ini tidak akan mengembalikan interval yang tidak berisi data apa pun. Untuk mendapatkan interval kosong tersebut kita bisa menggunakan fungsi generate_series .
SELECT generate_series(MIN(date_trunc('hour',timestamp_column)), max(date_trunc('minute',timestamp_column)),'5m') as interval_alias FROM TABLE_NAME
Hasil:
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
Sekarang untuk mendapatkan hasil dengan interval dengan kejadian nol kita hanya menggabungkan kedua kumpulan hasil .
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
Hasil akhirnya akan menyertakan rangkaian dengan semua interval 5 menit bahkan yang tidak memiliki nilai.
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
Interval dapat dengan mudah diubah dengan menyesuaikan parameter terakhir dari generate_series. Dalam kasus kami, kami menggunakan '5m' tetapi bisa jadi interval apa pun yang kami inginkan.
sumber
Anda sebaiknya menggunakan
GROUP BY UNIX_TIMESTAMP(time_stamp) DIV 300
daripada round (../ 300) karena pembulatan saya menemukan bahwa beberapa record dihitung menjadi dua set hasil yang dikelompokkan.sumber
DIV
MySQL adalah salahfloor()
satu divisi float yang aman denganBIGINT
s.Untuk postgres , saya merasa lebih mudah dan lebih akurat untuk menggunakan
date_trunc
fungsi, seperti:
select name, sum(count), date_trunc('minute',timestamp) as timestamp FROM table WHERE xxx GROUP BY name,date_trunc('minute',timestamp) ORDER BY timestamp
Anda dapat memberikan berbagai resolusi seperti 'menit', 'jam', 'hari' dll ... ke date_trunc.
sumber
5
sini untuk interval 5 menit?Kueri akan menjadi seperti ini:
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
sumber
Anda mungkin harus memecah stempel waktu Anda menjadi ymd: HM dan menggunakan DIV 5 untuk membagi menit menjadi bins 5 menit - sesuatu seperti
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
... dan kemudian futz output dalam kode klien untuk tampil sesuai keinginan Anda. Atau, Anda dapat membuat seluruh string tanggal menggunakan operator sql concat daripada mendapatkan kolom terpisah, jika Anda mau.
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'))
... dan kemudian kelompokkan itu
sumber
Tidak yakin apakah Anda masih membutuhkannya.
SELECT FROM_UNIXTIME(FLOOR((UNIX_TIMESTAMP(timestamp))/300)*300) AS t,timestamp,count(1) as c from users GROUP BY t ORDER BY t;
sumber
Bagaimana dengan yang ini:
select from_unixtime(unix_timestamp(timestamp) - unix_timestamp(timestamp) mod 300) as ts, sum(value) from group_interval group by ts order by ts ;
sumber
Saya menemukan bahwa dengan MySQL mungkin kueri yang benar adalah sebagai berikut:
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
Biarkan aku tahu apa yang kamu pikirkan.
sumber
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))
sumber