Geen opgeslagen procedures, tijdelijke tabellen, slechts één query en een efficiënt uitvoeringsplan met een index op de datumkolom:
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);
Het zou vrij duidelijk moeten zijn wat hier gebeurt, behalve deze bezwering:
floor(dateDiff('2012-12-31', dateStampColumn) / 30)
Die uitdrukking verschijnt meerdere keren en wordt geëvalueerd tot het aantal perioden van 30 dagen geleden dateStampColumn
is. dateDiff
geeft het verschil in dagen terug, deelt het door 30 om het in perioden van 30 dagen te krijgen en voert het allemaal door naar floor()
om het af te ronden op een geheel getal. Zodra we dit nummer hebben, kunnen we GROUP BY
het, en verder doen we een beetje wiskunde om dit getal terug te vertalen naar de begin- en einddatum van de periode.
Vervang '2012-12-31'
met now()
als je wilt. Hier zijn enkele voorbeeldgegevens:
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');
En het resultaat:
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
periode-eindpunten zijn inclusief.
Speel hiermee in SQL Fiddle .
Het is een beetje gek dat elke periode van 30 dagen met nul overeenkomende rijen niet in het resultaat wordt opgenomen. Als je dit zou kunnen combineren met een tabel met periodes, zou dat kunnen worden geëlimineerd. MySQL heeft echter niet zoiets als PostgreSQL's generate_series() , dus je moet ermee omgaan in je applicatie of proberen deze slimme hack .