Mysql
 sql >> Database >  >> RDS >> Mysql

Conta il numero di righe nei bin di 30 giorni

Nessuna procedura memorizzata, tabelle temporanee, solo una query e un piano di esecuzione efficiente con un indice nella colonna della data:

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

Dovrebbe essere abbastanza ovvio cosa sta succedendo qui, a parte questo incantesimo:

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

Tale espressione appare più volte e restituisce il numero di periodi di 30 giorni fa dateStampColumn è. dateDiff restituisce la differenza in giorni, dividila per 30 per ottenerla in periodi di 30 giorni e inviala a floor() per arrotondarlo a un numero intero. Una volta ottenuto questo numero, possiamo GROUP BY esso, e inoltre facciamo un po' di matematica per tradurre questo numero nelle date di inizio e fine del periodo.

Sostituisci '2012-12-31' con now() se preferisci. Ecco alcuni dati di esempio:

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

E il risultato:

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

gli endpoint del periodo sono inclusi.

Gioca con questo in SQL Fiddle .

C'è un po' di potenziale stupidità nel fatto che qualsiasi periodo di 30 giorni con zero righe corrispondenti non sarà incluso nel risultato. Se potessi unirti a questo contro una tabella di periodi, questo potrebbe essere eliminato. Tuttavia, MySQL non ha nulla di simile a generate_series() , quindi dovresti gestirlo nella tua applicazione o provare questo trucco intelligente .