sql >> Database >  >> RDS >> Mysql

Tel het aantal rijen in bakken voor 30 dagen

Geen opgeslagen procedures, tijdelijke tabellen, slechts één query en een efficiënt uitvoeringsplan met een index op de datumkolom:

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

Het zou vrij duidelijk moeten zijn wat hier gebeurt, behalve deze bezwering:

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

Die uitdrukking verschijnt meerdere keren en wordt geëvalueerd tot het aantal perioden van 30 dagen geleden dateStampColumn is. dateDiff geeft het verschil in dagen terug, deelt het door 30 om het in perioden van 30 dagen te krijgen en voert het allemaal door naar floor() om het af te ronden op een geheel getal. Zodra we dit nummer hebben, kunnen we GROUP BY het, en verder doen we een beetje wiskunde om dit getal terug te vertalen naar de begin- en einddatum van de periode.

Vervang '2012-12-31' met now() als je wilt. Hier zijn enkele voorbeeldgegevens:

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

En het resultaat:

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-eindpunten zijn inclusief.

Speel hiermee in SQL Fiddle .

Het is een beetje gek dat elke periode van 30 dagen met nul overeenkomende rijen niet in het resultaat wordt opgenomen. Als je dit zou kunnen combineren met een tabel met periodes, zou dat kunnen worden geëlimineerd. MySQL heeft echter niet zoiets als PostgreSQL's generate_series() , dus je moet ermee omgaan in je applicatie of proberen deze slimme hack .



  1. 3 manieren om rijen te retourneren die alfanumerieke tekens bevatten in SQL Server

  2. Kan geen verbinding maken met database:toegang geweigerd voor gebruiker ''@'localhost' tot database 'socialdb'

  3. Verschillende waarden matchen binnen één rij

  4. MySQL LOAD DATA INFILE met komma als decimaal scheidingsteken