Без съхранени процедури, временни таблици, само една заявка и ефективен план за изпълнение с индекс в колоната за дата:
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);
Трябва да е доста очевидно какво се случва тук, с изключение на това заклинание:
floor(dateDiff('2012-12-31', dateStampColumn) / 30)
Този израз се появява няколко пъти и се оценява до броя на периодите отпреди 30 дни dateStampColumn
е dateDiff
връща разликата в дни, разделете я на 30, за да я получите в периоди от 30 дни, и я подадете на floor()
за да го закръглите до цяло число. След като имаме този номер, можем да GROUP BY
и освен това правим малко математика, за да преведем това число обратно в началната и крайната дата на периода.
Заменете '2012-12-31'
с now()
ако предпочиташ. Ето някои примерни данни:
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');
И резултатът:
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
крайните точки на периода са включени.
Играйте с това в SQL Fiddle .
Има малко потенциална глупост в това, че всеки 30-дневен период с нулеви съвпадащи редове няма да бъде включен в резултата. Ако можете да присъедините това към таблица с периоди, това може да бъде елиминирано. MySQL обаче няма нищо подобно на generate_series() на PostgreSQL a> , така че ще трябва да се справите с него в приложението си или да опитате този умен хак .