MySQL Sorgu Grubu gün / ay / yıl


649

Bir TIMESTAMPalana sahip bir yıl, ay veya gün gibi belirli bir sürede kaç kayda sahip olduğumu saymak için basit bir sorgu yapmak mümkün müdür :

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

Ya da:

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

Aylık bir istatistiğe sahip olmak.

Teşekkürler!


1
Sanırım GROUP BY record_date.MONTHilk kod pasajınızda olması gerekiyordu ?
chiccodoro

Yanıtlar:


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

MySQL'deki tarih ve saat işlevlerine göz atın .


27
Kayıtların yıllar sürdüğü bazı durumlarda daha fazla netlik için fazladan bir sütun eklemek isteyebilirsiniz. SELECT COUNT (event_id), DATE_FORMAT (event_start, '% Y /% m')
Ric

Basit tam örnek: SELECT count(*), record_date FROM anytable WHERE anytable.anycolumn = 'anycondition' GROUP BY YEAR(record_date), month(record_date);not: kayıt_tarihi TIMESTAMP bir tarih türüdür
renedet

Muhtemelen bu bir COUNT takma sütun ile MySQL 5.7 üzerinde çalışmadı (hata yok, sıfır sonuç var) bahsetmeye değer. Bu alanları takma adla seçmek için değiştirdiğimde, takma ada göre gruplayabilirim. Bu, yerel bir ortamda çalışan standart MySQL 5.7 docker görüntüsüdür, bu yüzden neden hata yapmadığını veya sonuç döndürmediğini bilmiyorum.
MrMesees

3
Tanrım, bunu daha önce bilseydim ... mysql'nin bir satırda yapabileceği bir çok PHP satırı.
gece

230
GROUP BY DATE_FORMAT(record_date, '%Y%m')

Not (öncelikli olarak, potansiyel downvoters için). Şu anda, bu diğer öneriler kadar etkili olmayabilir. Yine de, diğer çözümlerin ne kadar hızlı olduğunu görmeye hizmet edebilecek bir alternatif ve bir de bırakıyorum. (Farkı görene kadar yavaştan gerçekten hızlı bir şekilde anlayamazsınız.) Ayrıca, zaman geçtikçe, MySQL'in motorunda optimizasyon ile ilgili olarak bu çözümü yapmak için bazı değişiklikler yapılabilir (belki de değil) uzaktaki noktayı, gelecekte diğerlerinin çoğuyla oldukça karşılaştırılabilir hale getirmek.


3
Biçim işlevi tarih sütununda bir dizin kullanmak mümkün olmaz çünkü bu iyi performans bir duygu var.
Sonny

@Stv: O zaman @ fu-chi'nin cevabını düşünmek isteyebilirsiniz . Anlayabildiğim kadarıyla, hem cevap hem de benimki gruplandırma ifadeleri aynı şeyi değerlendirir, ancak EXTRACT()bundan daha verimli olabilir DATE_FORMAT(). (Doğru test için bir MySQL'im yok.)
Andriy M

45

bunu dene

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

Daha az gruplama kullanıldığından ve işlev bir sayı değeri döndürdüğünden EXTRACT (birim FROM tarihi) işlevi daha iyidir.

Gruplama sırasındaki karşılaştırma koşulu DATE_FORMAT işlevinden daha hızlı olacaktır (dize değeri döndürür). SQL karşılaştırma koşulu (NEREDE, HAVING, ORDER BY, GROUP BY) için dize olmayan değer döndüren işlev | alanını kullanmayı deneyin.


43

Yukarıdaki 'NEREDE' ifadesini kullanmayı denedim, kimse düzeltmediği için doğru olduğunu düşündüm ama yanılmışım; bazı aramalardan sonra bu kod WHERE deyimi için doğru formül olduğunu öğrendim böylece kod şöyle olur:

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

30

Aramanız birkaç yıldan fazlaysa ve yine de aylık olarak gruplamak istiyorsanız, şunu öneririm:

versiyon 1:

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

sürüm # 2 (daha verimli) :

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

Bu sürümleri büyük bir tabloda 1,357,918 satırla karşılaştırdım () ve 2. sürümün daha iyi sonuç verdiği görülüyor.

sürüm1 (10 yürütme ortalaması) : 1.404 saniye
sürüm2 (10 yürütme ortalaması) : 0.780 saniye

( SQL_NO_CACHEMySQL'in sorgulara önbelleğe alınmasını önlemek için anahtar eklendi.)


1
@ Fu-chi'nin testlerinize önerisini dahil etmeyi düşünün, daha da verimli olabilir. Ayrıca, test ettiniz GROUP BY YEAR(record_date)*100 + MONTH(record_date), ama neden de test etmiyorsunuz GROUP BY YEAR(record_date), MONTH(record_date)?
Andriy M

2
COUNT (1) numaralı COUNT (*) kullanırsanız, daha da hızlı olur ve sonuç verileri aynı olur.
Pa0l0

2
*1002. ayette bu nedir ? Şimdiden teşekkürler.
Avión

1
*100toYEAR(record_date)*100 + MONTH(record_date) == DATE_FORMAT(record_date, '%Y%m')
Phu Duy

17

MySQL'de tarihe göre gruplandırmak istiyorsanız aşağıdaki kodu kullanın:

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

Umarım bu konuyu bulanlar için biraz zaman kazandırır.


6
Ayrıca MONTH(record_date), birkaç ay boyunca hesaba katmak için de gruplandırmanız gerektiğini unutmayın .
Webnet

14

Belirli bir yıla (örneğin 2000) ilişkin kayıtları filtrelemek istiyorsanız, WHEREmaddeyi şu şekilde optimize edin :

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.

Onun yerine:

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

Sonuçlar, 300 bin satır ve tarih sütununda dizin içeren bir tabloya göre oluşturuldu.

Maddeye gelince GROUP BY, üç değişkeni yukarıda belirtilen tabloya göre test ettim; sonuçlar burada:

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.

Sonuncusu kazanan.


10

Şu anda aktif olan benzer şekilde performans gösteren, daha kısa ve daha esnek bir alternatif ile eksiksiz ve basit bir çözüm:

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

7

En son aya göre sipariş edilen her yılın aylık satır sayısı ile aylık bir istatistik almak istiyorsanız, şunu deneyin:

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

7

Bunu sadece GROUP BY'de Mysql DATE_FORMAT () işleviyle yapabilirsiniz. Kayıtların birkaç yıl sonra aynı ayın farklı yıllarda gerçekleştiği gibi bazı durumlarda ek netlik için fazladan bir sütun eklemek isteyebilirsiniz. Lütfen başlamadan önce bunu okuyun. Umarım sizin için çok yararlı olmalıdır. İşte anlayışınız için örnek sorgu

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 ');

4

Aşağıdaki sorgu benim için Oracle Database 12c Sürüm 12.1.0.1.0'da çalıştı

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

2

Ben böyle bir yıl grup seçimi optimize tercih:

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

Bu şekilde, yılı bir kerede, örneğin '2009'adlandırılmış bir parametreyle bağlayabilirsiniz ve ayrı olarak ekleme '-01-01'veya aktarma konusunda endişelenmenize gerek yoktur '2010'.

Ayrıca, sadece satır sayma ve gibi muhtemelen idasla NULL, ben tercih COUNT(*)etmek COUNT(id).


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') ---> MAYIS

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


Bu çok çok yavaş olurdu.
earl3s
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.