MySQL'de haftaya göre nasıl gruplanır?


92

Oracle'ın tablo sunucusu yerleşik bir işlev sunar TRUNC(timestamp,'DY'). Bu işlev herhangi bir zaman damgasını önceki Pazar gece yarısına dönüştürür. Bunu MySQL'de yapmanın en iyi yolu nedir?

Oracle ayrıca TRUNC(timestamp,'MM')bir zaman damgasını, gerçekleştiği ayın ilk gününde gece yarısına dönüştürmeyi teklif eder. MySQL'de bu basittir:

TIMESTAMP(DATE_FORMAT(timestamp, '%Y-%m-01'))

Ancak bu DATE_FORMATnumara haftalarca işe yaramayacak. WEEK(timestamp)İşlevin farkındayım , ancak yıl içinde hafta sayısını gerçekten istemiyorum; bu şeyler çok yıllık işler içindir.


kısaltmayı (sysdate, 'W'), kesmeyi değil (sysdate, 'DY') kastediyorsunuz
David Aldridge,

TRUNC(date, 'DY' )Pazar başlangıcı olan haftalar alır. 'W'en azından benim sistemimde Pazartesi günü başlıyor.
O. Jones

Yanıtlar:


123

Her iki kullanabilir YEAR(timestamp)ve WEEK(timestamp)ve bu ifadelerin ikisi de kullanabilir SELECTve GROUP BYfıkra.

Aşırı zarif değil, ama işlevsel ...

Ve elbette bu iki tarih bölümünü tek bir ifadede de birleştirebilirsiniz, yani

SELECT CONCAT(YEAR(timestamp), '/', WEEK(timestamp)), etc...
FROM ...
WHERE ..
GROUP BY CONCAT(YEAR(timestamp), '/', WEEK(timestamp))

Düzenleme : As Martin Puan size de kullanabilirsiniz YEARWEEK(mysqldatefield)çıkış yukarıda uzun formülü olarak dost göz olarak olmasa da, işlevini.


Düzenleme 2 [3 1/2 yıl sonra!]:
YEARWEEK(mysqldatefield)İsteğe bağlı ikinci bağımsız değişken ( mode) 0 veya 2 olarak ayarlanmışsa, muhtemelen tam haftalara göre toplamanın en iyi yoludur (yani 1 Ocak'tan sonra kesişen haftalar dahil), eğer öyleyse ne isteniyor. YEAR() / WEEK()Başlangıçta bu cevap önerilen yaklaşım bölünme etkisini böyle için toplanmış veri vardır "straddling" eski yıla tane yeni yıl ile: biri ikiye haftadır.
Her yıl, her iki ucunda bir tane olmak üzere iki kısmi haftaya sahip olma pahasına temiz bir kesim, muhasebede vb. Genellikle arzu edilir ve bu nedenle YEAR() / WEEK()yaklaşım daha iyidir.


12
YEARWEEK()INT(6)sıralama / katılmanın / gruplamanın daha hızlı olacağına inandığım bir sonuç veriyor
KCD

@mjv: İki yıl aynı haftayı paylaşırsa ne olur? bunun gibi 31-12-2012 - 6-1-2013 (Pzt - Paz). Bunun herhangi bir çözümü var mı ?
hardik

@hardik: Düzenleme 2. Kişinin ihtiyaçlarına bağlı olarak, yılın son / ilk kısmi haftasını bölmek yerine tam haftalarla çalışmak isterse YEARWEEK () toplama için daha iyi bir anahtar olabilir.
mjv

@mjv işte bu bağlantı
hardik

"zaman damgasının" masamdaki gibi bir tam sayı olmadığından emin olun. WEEK (zaman damgası), geçerli bir argüman olarak tarih / zaman damgası sütun türünü alır
Usman Shaukat

37

Yukarıdaki kabul edilen cevap benim için işe yaramadı, çünkü haftaları kronolojik sıraya göre değil alfabetik sıraya göre sıraladı:

2012/1
2012/10
2012/11
...
2012/19
2012/2

İşte haftaya göre sayma ve gruplama çözümüm:

SELECT CONCAT(YEAR(date), '/', WEEK(date)) AS week_name, 
       YEAR(date), WEEK(date), COUNT(*)
FROM column_name
GROUP BY week_name
ORDER BY YEAR(DATE) ASC, WEEK(date) ASC

Oluşturur:

YEAR/WEEK   YEAR   WEEK   COUNT
2011/51     2011    51      15
2011/52     2011    52      14
2012/1      2012    1       20
2012/2      2012    2       14
2012/3      2012    3       19
2012/4      2012    4       19

5
tarihe ( ORDER BY date ASC) göre sipariş vermek de işe yaramalı
Fender

36

Anladım ... biraz hantal, ama işte burada.

FROM_DAYS(TO_DAYS(TIMESTAMP) -MOD(TO_DAYS(TIMESTAMP) -1, 7))

Ve, iş kurallar hafta Pazartesi günleri başlar dersem, değiştirmek -1için -2.


Düzenle

Yıllar geçti ve sonunda bunu yazmaya başladım. http://www.plumislandmedia.net/mysql/sql-reporting-time-intervals/


@Ollie - Okunabilirliğe yardımcı olması için DAYOFWEEK () veya WEEKDAY () kullanmayı düşünürdüm.
martin clayton

1
Martin, bunu düşündüm ve bu işlevlerin Pazartesi-Pazar günleri 0-6 arasında çalıştığını keşfettim. İş kurallarım, haftaların Pazar günü 00: 00'da başladığını söylüyor, bu nedenle WEEKDAY işleri biraz çirkinleşti. Okunabilirlik konusunda haklısın.
O. Jones

@OllieJones mükemmel! Çok teşekkür ederim!
Joe Cheng

1
Harika çözüm ve makale. Teşekkür ederim!
Jeremy Wiggins

"Pazartesi" yi ilk gün olarak ayarlamanın bir yolu var mı?
Pedro Joaquín

25

YEARWEEK () işlevini kullanarak birleştirilmiş yıl ve hafta numarasını (200945) alabilirsiniz . Hedefinizi doğru anlarsam, çok yıllı verilerinizi gruplandırmanıza olanak tanır.

Haftanın başlangıcı için gerçek zaman damgasına ihtiyacınız varsa, bu daha az hoş:

DATE_SUB( field, INTERVAL DAYOFWEEK( field ) - 1 DAY )

Aylık sıralama için, LAST_DAY () işlevini düşünebilirsiniz - sıralama ayın son gününe göre olacaktır, ancak bu ayın ilk gününe göre sıralamaya eşdeğer olmalıdır ... değil mi?


1
+1 Martin. Duh benim için YEARWEEK () 'i unuttum ... Sadece pek kullanmıyorum.
mjv

4

Sadece şunu seçin:

DATE_FORMAT($yourDate, \'%X %V\') as week

Ve

group_by(week);

aya göre nasıl
gruplanır

Verileri sürekli olarak değil, yalnızca belirli bir tarih için
yakalar

2

"Hafta sonu" tarihine ihtiyacınız varsa, bu da işe yarayacaktır. Bu, her hafta için kayıt sayısını sayacaktır. Örnek: 1/2/2010 ile 1/8/2010 arasında (dahil) üç iş emri oluşturulmuşsa ve 5 1/9/2010 ile 1/16/2010 arasında (dahil) oluşturulmuşsa, bu şu şekilde olacaktır:

3 1/8/2010
5 1/16/2010

Tarih saat alanımı kesmek için ekstra DATE () işlevini kullanmak zorunda kaldım.

SELECT COUNT(*), DATE_ADD( DATE(wo.date_created), INTERVAL (7 - DAYOFWEEK( wo.date_created )) DAY) week_ending
FROM work_order wo
GROUP BY week_ending;
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.