Pas de procédures stockées, de tables temporaires, une seule requête et un plan d'exécution efficace avec un index sur la colonne de date :
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);
Ce qui se passe ici devrait être assez évident, à l'exception de cette incantation :
floor(dateDiff('2012-12-31', dateStampColumn) / 30)
Cette expression apparaît plusieurs fois, et elle évalue le nombre de périodes de 30 jours il y a dateStampColumn
est. dateDiff
renvoie la différence en jours, divisez-la par 30 pour l'obtenir en périodes de 30 jours, et alimentez le tout dans floor()
pour l'arrondir à un nombre entier. Une fois que nous avons ce numéro, nous pouvons GROUP BY
puis nous faisons un peu de calcul pour traduire ce nombre en dates de début et de fin de la période.
Remplacer '2012-12-31'
avec now()
si tu préfères. Voici quelques exemples de données :
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');
Et le résultat :
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
les points de terminaison de la période sont inclus.
Jouez avec cela dans SQL Fiddle .
Il y a un peu de maladresse potentielle dans la mesure où toute période de 30 jours avec zéro ligne correspondante ne sera pas incluse dans le résultat. Si vous pouviez joindre cela à un tableau de périodes, cela pourrait être éliminé. Cependant, MySQL n'a rien comme generate_series() , vous devrez donc vous en occuper dans votre application ou essayer ce hack intelligent .