wake-up-neo.com

Wie gruppiere ich nach Woche in MySQL?

Der Oracle-Tabellenserver bietet eine integrierte Funktion, TRUNC(timestamp,'DY'). Diese Funktion konvertiert jeden Zeitstempel des vorherigen Sonntags in Mitternacht. Was ist der beste Weg, um dies in MySQL zu tun?

Oracle bietet auch TRUNC(timestamp,'MM') an, um einen Zeitstempel am ersten Tag des Monats, in dem er auftritt, in Mitternacht umzuwandeln. In MySQL ist dies ganz einfach:

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

Aber dieser DATE_FORMAT Trick wird wochenlang nicht funktionieren. Mir ist die Funktion WEEK(timestamp) bekannt, aber ich möchte wirklich keine Wochennummer innerhalb des Jahres. Dieses Zeug ist für mehrjährige Arbeit.

75
O. Jones

Fand es heraus ... es ist ein bisschen umständlich, aber hier ist es.

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

Und wenn Ihre Geschäftsregeln besagen, dass Ihre Wochen montags beginnen, ändern Sie das -1 bis -2.


Bearbeiten

Jahre sind vergangen und ich bin endlich dazu gekommen, dies aufzuschreiben. http://www.plumislandmedia.net/mysql/sql-reporting-time-intervals/

25
O. Jones

Sie können sowohl YEAR(timestamp) als auch WEEK(timestamp) verwenden und diese beiden Ausdrücke in SELECT und die GROUP BY - Klausel.

Nicht übermäßig elegant, aber funktional ...

Und natürlich können Sie diese beiden Datumsteile auch in einem einzigen Ausdruck kombinieren, d. H. So etwas wie

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

Bearbeiten : Wie Martin weist darauf hin können Sie auch das YEARWEEK(mysqldatefield) verwenden Funktion, obwohl seine Ausgabe nicht so augenfreundlich ist wie die längere Formel oben.


Edit 2 [3 1/2 Jahre später!]:
YEARWEEK(mysqldatefield) mit dem optionalen zweiten Argument ( mode ) auf 0 oder 2 ist wahrscheinlich der beste Weg zu complete Wochen aggregieren (dh auch für Wochen, die über den 1. Januar hinausreichen), wenn dies gewünscht wird. Der YEAR() / WEEK() -Ansatz, der ursprünglich in dieser Antwort vorgeschlagen wurde, bewirkt, dass die aggregierten Daten für diese "Spreizung" Wochen in zwei aufgeteilt werden: eine mit dem vorherigen Jahr, eine mit dem neuen Jahr.
In der Buchhaltung usw. wird häufig ein Clean-Cut jedes Jahr auf Kosten von bis zu zwei Teilwochen, eine an beiden Enden, gewünscht, und aus diesem Grund ist der Ansatz YEAR() / WEEK() besser.

102
mjv

Die oben akzeptierte Antwort hat bei mir nicht funktioniert, da die Wochen in alphabetischer Reihenfolge und nicht in chronologischer Reihenfolge sortiert wurden:

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

Hier ist meine Lösung zum Zählen und Gruppieren nach Woche:

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

Erzeugt:

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
26
B Seven

Sie können die verkettete Jahres- und Wochennummer (200945) mit der Funktion YEARWEEK () abrufen. Wenn ich Ihr Ziel richtig verstehe, sollten Sie die Möglichkeit haben, Ihre mehrjährigen Daten zu gruppieren.

Wenn Sie den tatsächlichen Zeitstempel für den Beginn der Woche benötigen, ist es weniger schön:

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

Bei einer monatlichen Bestellung können Sie die Funktion LAST_DAY () in Betracht ziehen. Die Sortierung erfolgt nach dem letzten Tag des Monats. Dies sollte jedoch der Sortierung nach dem ersten Tag des Monats entsprechen ?

22
martin clayton

Fügen Sie dies einfach in die Auswahl ein:

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

Und

group_by(week);
4
Xavier

Wenn Sie das Datum "Wochenende" benötigen, funktioniert dies ebenfalls. Dadurch wird die Anzahl der Datensätze für jede Woche gezählt. Beispiel: Wenn drei Arbeitsaufträge zwischen (einschließlich) 1/2/2010 und 1/8/2010 erstellt wurden und 5 zwischen (einschließlich) 1/9/2010 und 1/16/2010 erstellt wurden, würde dies Folgendes zurückgeben:

3 08.01.2010
5 1/16/2010

Ich musste die zusätzliche DATE () - Funktion verwenden, um mein Datum/Uhrzeit-Feld abzuschneiden.

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;

2
Randy