Mysql
 sql >> Base de données >  >> RDS >> Mysql

Compter le nombre de rangées dans les tranches de 30 jours

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 .