Keine gespeicherten Prozeduren, temporäre Tabellen, nur eine Abfrage und ein effizienter Ausführungsplan mit einem Index für die Datumsspalte:
select
subdate(
'2012-12-31',
floor(dateDiff('2012-12-31', dateStampColumn) / 30) * 30 + 30 - 1
) as "period starting",
subdate(
'2012-12-31',
floor(dateDiff('2012-12-31', dateStampColumn) / 30) * 30
) as "period ending",
count(*)
from
YOURTABLE
group by floor(dateDiff('2012-12-31', dateStampColumn) / 30);
Es sollte ziemlich offensichtlich sein, was hier passiert, abgesehen von dieser Beschwörung:
floor(dateDiff('2012-12-31', dateStampColumn) / 30)
Dieser Ausdruck erscheint mehrmals und ergibt die Anzahl von 30-Tage-Perioden vor dateStampColumn
ist. dateDiff
gibt die Differenz in Tagen zurück, teilt sie durch 30, um sie in 30-Tage-Perioden zu erhalten, und füttert alles mit floor()
um es auf eine ganze Zahl zu runden. Sobald wir diese Nummer haben, können wir GROUP BY
es, und weiter rechnen wir ein wenig, um diese Zahl zurück in das Anfangs- und Enddatum des Zeitraums zu übersetzen.
Ersetzen Sie '2012-12-31'
mit now()
wenn Sie es vorziehen. Hier sind einige Beispieldaten:
CREATE TABLE YOURTABLE
(`Id` int, `dateStampColumn` datetime);
INSERT INTO YOURTABLE
(`Id`, `dateStampColumn`)
VALUES
(1, '2012-10-15 02:00:00'),
(1, '2012-10-17 02:00:00'),
(1, '2012-10-30 02:00:00'),
(1, '2012-10-31 02:00:00'),
(1, '2012-11-01 02:00:00'),
(1, '2012-11-02 02:00:00'),
(1, '2012-11-18 02:00:00'),
(1, '2012-11-19 02:00:00'),
(1, '2012-11-21 02:00:00'),
(1, '2012-11-25 02:00:00'),
(1, '2012-11-25 02:00:00'),
(1, '2012-11-26 02:00:00'),
(1, '2012-11-26 02:00:00'),
(1, '2012-11-24 02:00:00'),
(1, '2012-11-23 02:00:00'),
(1, '2012-11-28 02:00:00'),
(1, '2012-11-29 02:00:00'),
(1, '2012-11-30 02:00:00'),
(1, '2012-12-01 02:00:00'),
(1, '2012-12-02 02:00:00'),
(1, '2012-12-15 02:00:00'),
(1, '2012-12-17 02:00:00'),
(1, '2012-12-18 02:00:00'),
(1, '2012-12-19 02:00:00'),
(1, '2012-12-21 02:00:00'),
(1, '2012-12-25 02:00:00'),
(1, '2012-12-25 02:00:00'),
(1, '2012-12-26 02:00:00'),
(1, '2012-12-26 02:00:00'),
(1, '2012-12-24 02:00:00'),
(1, '2012-12-23 02:00:00'),
(1, '2012-12-31 02:00:00'),
(1, '2012-12-30 02:00:00'),
(1, '2012-12-28 02:00:00'),
(1, '2012-12-28 02:00:00'),
(1, '2012-12-30 02:00:00');
Und das Ergebnis:
period starting period ending count(*)
2012-12-02 2012-12-31 17
2012-11-02 2012-12-01 14
2012-10-03 2012-11-01 5
Periodenendpunkte sind inklusive.
Spielen Sie damit in SQL Fiddle .
Es ist ein bisschen albern, dass jeder 30-Tage-Zeitraum mit null übereinstimmenden Zeilen nicht in das Ergebnis aufgenommen wird. Wenn Sie dies mit einer Periodentabelle verbinden könnten, könnte dies eliminiert werden. MySQL hat jedoch nichts wie PostgreSQLs generate_series() , also müssten Sie sich in Ihrer Anwendung darum kümmern oder ausprobieren diesen cleveren Hack .