Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Zählen Sie die Anzahl der Zeilen in 30-Tage-Bins

Keine gespeicherten Prozeduren, temporäre Tabellen, nur eine Abfrage und ein effizienter Ausführungsplan mit einem Index für die Datumsspalte:

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);

Es sollte ziemlich offensichtlich sein, was hier passiert, abgesehen von dieser Beschwörung:

floor(dateDiff('2012-12-31', dateStampColumn) / 30)

Dieser Ausdruck erscheint mehrmals und ergibt die Anzahl von 30-Tage-Perioden vor dateStampColumn ist. dateDiff gibt die Differenz in Tagen zurück, teilt sie durch 30, um sie in 30-Tage-Perioden zu erhalten, und füttert alles mit floor() um es auf eine ganze Zahl zu runden. Sobald wir diese Nummer haben, können wir GROUP BY es, und weiter rechnen wir ein wenig, um diese Zahl zurück in das Anfangs- und Enddatum des Zeitraums zu übersetzen.

Ersetzen Sie '2012-12-31' mit now() wenn Sie es vorziehen. Hier sind einige Beispieldaten:

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');

Und das Ergebnis:

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

Periodenendpunkte sind inklusive.

Spielen Sie damit in SQL Fiddle .

Es ist ein bisschen albern, dass jeder 30-Tage-Zeitraum mit null übereinstimmenden Zeilen nicht in das Ergebnis aufgenommen wird. Wenn Sie dies mit einer Periodentabelle verbinden könnten, könnte dies eliminiert werden. MySQL hat jedoch nichts wie PostgreSQLs generate_series() , also müssten Sie sich in Ihrer Anwendung darum kümmern oder ausprobieren diesen cleveren Hack .