MySQL Query GROUP OLEH hari / bulan / tahun

649

Apakah mungkin membuat kueri sederhana untuk menghitung berapa banyak catatan yang saya miliki dalam periode waktu tertentu seperti setahun, bulan, atau hari, memiliki TIMESTAMPbidang, seperti:

SELECT COUNT(id)
FROM stats
WHERE record_date.YEAR = 2009
GROUP BY record_date.YEAR

Atau bahkan:

SELECT COUNT(id)
FROM stats
GROUP BY record_date.YEAR, record_date.MONTH

Untuk memiliki statistik bulanan.

Terima kasih!

Fernando Barrocal
sumber
1
Saya kira itu seharusnya ada GROUP BY record_date.MONTHdalam cuplikan kode pertama Anda?
chiccodoro

Jawaban:

1012
GROUP BY YEAR(record_date), MONTH(record_date)

Lihat fungsi tanggal dan waktu di MySQL.

codelogic
sumber
27
Anda mungkin ingin menambahkan kolom tambahan untuk kejelasan tambahan dalam beberapa kasus seperti di mana catatan rentang beberapa tahun. SELECT COUNT (event_id), DATE_FORMAT (event_start, '% Y /% m')
Ric
Contoh lengkap sederhana: SELECT count(*), record_date FROM anytable WHERE anytable.anycolumn = 'anycondition' GROUP BY YEAR(record_date), month(record_date);note: record_date adalah tipe tanggal TIMESTAMP
renedet
Mungkin layak disebut ini tidak berjalan di MySQL 5.7 saya dengan kolom alias COUNT (tidak ada kesalahan, saya mendapat hasil nol). Ketika saya berubah untuk memilih bidang-bidang tersebut dengan alias, saya kemudian dapat mengelompokkan berdasarkan alias. Ini adalah gambar standar MySQL 5.7 buruh pelabuhan yang berjalan di lingkungan lokal jadi saya tidak tahu mengapa itu tidak kesalahan atau mengembalikan hasil.
MrMesees
3
Ya Tuhan, jika saya tahu ini sebelumnya ... begitu banyak baris PHP untuk melakukan sesuatu yang dapat dilakukan mysql dalam satu baris.
malam
230
GROUP BY DATE_FORMAT(record_date, '%Y%m')

Catatan (terutama, untuk calon downvoters). Saat ini, ini mungkin tidak seefisien saran lainnya. Namun, saya meninggalkannya sebagai alternatif, dan satu juga, yang dapat berfungsi dalam melihat seberapa cepat solusi lain. (Untuk Anda tidak dapat benar-benar tahu cepat dari lambat sampai Anda melihat perbedaannya.) Juga, seiring berjalannya waktu, perubahan dapat dilakukan pada mesin MySQL terkait dengan optimasi untuk membuat solusi ini, di beberapa (mungkin, tidak begitu jauh) poin di masa depan, untuk menjadi sangat sebanding dalam efisiensi dengan kebanyakan orang lain.

Andriy M
sumber
3
Saya merasa ini tidak akan berfungsi dengan baik karena fungsi format tidak akan dapat menggunakan indeks pada kolom tanggal.
Sonny
@Stv: Anda mungkin ingin mempertimbangkan jawaban @ fu-chi . Sejauh yang saya tahu, ekspresi pengelompokan baik di jawaban dan saya mengevaluasi hal yang sama tetapi EXTRACT()mungkin lebih efisien daripada DATE_FORMAT(). (Saya tidak punya MySQL untuk pengujian yang tepat.)
Andriy M
45

coba yang ini

SELECT COUNT(id)
FROM stats
GROUP BY EXTRACT(YEAR_MONTH FROM record_date)

Fungsi EXTRACT (unit FROM date) lebih baik karena lebih sedikit pengelompokan yang digunakan dan fungsi mengembalikan nilai angka.

Kondisi perbandingan saat pengelompokan akan lebih cepat daripada fungsi DATE_FORMAT (yang mengembalikan nilai string). Coba gunakan function | field yang mengembalikan nilai non-string untuk kondisi perbandingan SQL (WHERE, HAVING, ORDER BY, GROUP BY).

fu-chi
sumber
43

Saya mencoba menggunakan pernyataan 'DI MANA' di atas, saya pikir itu benar karena tidak ada yang memperbaikinya tetapi saya salah; setelah beberapa pencarian saya menemukan bahwa ini adalah formula yang tepat untuk pernyataan WHERE sehingga kode menjadi seperti ini:

SELECT COUNT(id)  
FROM stats  
WHERE YEAR(record_date) = 2009  
GROUP BY MONTH(record_date)
dimazaid
sumber
30

Jika pencarian Anda lebih dari beberapa tahun, dan Anda masih ingin mengelompokkan setiap bulan, saya sarankan:

versi 1:

SELECT SQL_NO_CACHE YEAR(record_date), MONTH(record_date), COUNT(*)
FROM stats
GROUP BY DATE_FORMAT(record_date, '%Y%m')

versi # 2 (lebih efisien) :

SELECT SQL_NO_CACHE YEAR(record_date), MONTH(record_date), COUNT(*)
FROM stats
GROUP BY YEAR(record_date)*100 + MONTH(record_date)

Saya membandingkan versi ini di atas meja besar dengan 1.357.918 baris (), dan versi ke-2 tampaknya memiliki hasil yang lebih baik.

versi1 (rata-rata 10 eksekusi) : 1,404 detik
versi2 (rata-rata 10 eksekusi) : 0,780 detik

( SQL_NO_CACHEkunci ditambahkan untuk mencegah MySQL dari CACHING ke kueri.)

mr.baby123
sumber
1
Pertimbangkan untuk memasukkan saran @ fu-chi ke dalam pengujian Anda, itu mungkin terbukti lebih efisien. Juga, Anda diuji GROUP BY YEAR(record_date)*100 + MONTH(record_date), tetapi mengapa tidak menguji GROUP BY YEAR(record_date), MONTH(record_date)juga?
Andriy M
2
Jika Anda menggunakan COUNT (1) memasang COUNT (*) itu akan lebih cepat, dan data hasilnya sama.
Pa0l0
2
Apa itu *100di versión # 2? Terima kasih sebelumnya.
Avion
1
*100keYEAR(record_date)*100 + MONTH(record_date) == DATE_FORMAT(record_date, '%Y%m')
Phu Duy
17

Jika Anda ingin mengelompokkan berdasarkan tanggal di MySQL, gunakan kode di bawah ini:

 SELECT COUNT(id)
 FROM stats
 GROUP BY DAYOFMONTH(record_date)

Semoga ini menghemat waktu bagi mereka yang akan menemukan utas ini.

Haijerome
sumber
6
Penting untuk dicatat bahwa Anda juga perlu dikelompokkan berdasarkan MONTH(record_date)juga untuk akun selama beberapa bulan.
Webnet
14

Jika Anda ingin memfilter catatan untuk tahun tertentu (mis. 2000), maka optimalkan WHEREklausa seperti ini:

SELECT MONTH(date_column), COUNT(*)
FROM date_table
WHERE date_column >= '2000-01-01' AND date_column < '2001-01-01'
GROUP BY MONTH(date_column)
-- average 0.016 sec.

Dari pada:

WHERE YEAR(date_column) = 2000
-- average 0.132 sec.

Hasilnya dihasilkan terhadap tabel yang berisi 300 ribu baris dan indeks pada kolom tanggal.

Adapun GROUP BYklausa, saya menguji tiga varian terhadap tabel yang disebutkan di atas; berikut hasilnya:

SELECT YEAR(date_column), MONTH(date_column), COUNT(*)
FROM date_table
GROUP BY YEAR(date_column), MONTH(date_column)
-- codelogic
-- average 0.250 sec.

SELECT YEAR(date_column), MONTH(date_column), COUNT(*)
FROM date_table
GROUP BY DATE_FORMAT(date_column, '%Y%m')
-- Andriy M
-- average 0.468 sec.

SELECT YEAR(date_column), MONTH(date_column), COUNT(*)
FROM date_table
GROUP BY EXTRACT(YEAR_MONTH FROM date_column)
-- fu-chi
-- average 0.203 sec.

Yang terakhir adalah pemenangnya.

Salman A
sumber
10

Solusi lengkap dan sederhana dengan alternatif yang sama namun lebih pendek dan lebih fleksibel saat ini aktif:

SELECT COUNT(*) FROM stats
-- GROUP BY YEAR(record_date), MONTH(record_date), DAYOFMONTH(record_date)
GROUP BY DATE_FORMAT(record_date, '%Y-%m-%d')
Cees Timmerman
sumber
7

Jika Anda ingin mendapatkan statistik bulanan dengan jumlah baris per bulan setiap tahun yang dipesan oleh bulan terbaru, cobalah ini:

SELECT count(id),
      YEAR(record_date),
      MONTH(record_date) 
FROM `table` 
GROUP BY YEAR(record_date),
        MONTH(record_date) 
ORDER BY YEAR(record_date) DESC,
        MONTH(record_date) DESC
pengguna3019799
sumber
7

Anda dapat melakukan ini hanya fungsi DATE_FORMAT () Mysql di GROUP BY. Anda mungkin ingin menambahkan kolom tambahan untuk kejelasan tambahan dalam beberapa kasus seperti di mana catatan span beberapa tahun lalu bulan yang sama terjadi di tahun yang berbeda. Di sini ada begitu banyak opsi yang dapat Anda sesuaikan ini. Baca ini sebelum mulai. Semoga ini akan sangat membantu Anda. Berikut ini contoh permintaan untuk pengertian Anda

SELECT
    COUNT(id),
    DATE_FORMAT(record_date, '%Y-%m-%d') AS DAY,
    DATE_FORMAT(record_date, '%Y-%m') AS MONTH,
    DATE_FORMAT(record_date, '%Y') AS YEAR

FROM
    stats
WHERE
    YEAR = 2009
GROUP BY
    DATE_FORMAT(record_date, '%Y-%m-%d ');
Faisal
sumber
4

Permintaan berikut ini berfungsi untuk saya di Oracle Database 12c Release 12.1.0.1.0

SELECT COUNT(*)
FROM stats
GROUP BY 
extract(MONTH FROM TIMESTAMP),
extract(MONTH FROM TIMESTAMP),
extract(YEAR  FROM TIMESTAMP);
Minisha
sumber
2

Saya lebih suka mengoptimalkan pemilihan kelompok satu tahun seperti:

SELECT COUNT(*)
  FROM stats
 WHERE record_date >= :year 
   AND record_date <  :year + INTERVAL 1 YEAR;

Dengan cara ini Anda hanya dapat mengikat tahun sekaligus, misalnya '2009', dengan parameter bernama dan tidak perlu khawatir tentang menambah '-01-01'atau meneruskan secara '2010'terpisah.

Juga, seperti mungkin kita hanya menghitung baris dan idtidak pernah NULL, saya lebih memilih COUNT(*)untuk COUNT(id).

Arth
sumber
0

.... group by to_char(date, 'YYYY') -> 1989

.... group by to_char(date,'MM') -> 05

.... group by to_char(date,'DD') ---> 23

.... group by to_char(date,'MON') ---> MEI

.... group by to_char(date,'YY') ---> 89

aromita sen
sumber
Ini akan sangat sangat lambat.
earl3s