Ingen lagrede procedurer, midlertidige tabeller, kun én forespørgsel og en effektiv eksekveringsplan givet et indeks i datokolonnen:
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);
Det burde være ret indlysende, hvad der sker her, bortset fra denne besværgelse:
floor(dateDiff('2012-12-31', dateStampColumn) / 30)
Det udtryk vises flere gange, og det evalueres til antallet af 30-dages perioder siden dateStampColumn
er. dateDiff
returnerer forskellen i dage, divider den med 30 for at få den i 30-dages perioder, og feed det hele til floor()
at afrunde det til et heltal. Når vi har dette nummer, kan vi GROUP BY
det, og yderligere laver vi lidt matematik for at oversætte dette tal tilbage til periodens start- og slutdato.
Erstat '2012-12-31'
med now()
hvis du foretrækker det. Her er nogle eksempeldata:
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');
Og resultatet:
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 slutpunkter er inklusive.
Spil med dette i SQL Fiddle .
Der er en smule potentiel fjols i, at enhver 30-dages periode med nul matchende rækker ikke vil blive inkluderet i resultatet. Hvis du kunne slutte dig til dette mod en tabel med perioder, kunne det blive elimineret. MySQL har dog ikke noget som PostgreSQL's generate_series() , så du bliver nødt til at håndtere det i din ansøgning eller prøv dette smarte hack .