sql >> Databasteknik >  >> RDS >> Mysql

Räkna antalet rader i 30 dagars papperskorgar

Inga lagrade procedurer, temporära tabeller, bara en fråga och en effektiv exekveringsplan givet ett index i datumkolumnen:

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

Det borde vara ganska uppenbart vad som händer här, förutom denna besvärjelse:

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

Det uttrycket förekommer flera gånger, och det utvärderas till antalet 30-dagarsperioder sedan dateStampColumn är. dateDiff returnerar skillnaden i dagar, dividera den med 30 för att få den i 30-dagarsperioder och mata allt till floor() för att avrunda det till ett heltal. När vi har det här numret kan vi GROUP BY det, och vidare gör vi lite matte för att översätta detta nummer tillbaka till periodens start- och slutdatum.

Ersätt '2012-12-31' med now() om du föredrar. Här är några exempeldata:

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

Och resultatet:

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

periodslutpunkter är inklusive.

Lek med detta i SQL Fiddle .

Det finns lite potentiell fånighet i att en 30-dagarsperiod med noll matchande rader inte kommer att inkluderas i resultatet. Om du kunde slå ihop detta mot en tabell med perioder, skulle det kunna elimineras. MySQL har dock inget liknande PostgreSQL:s generate_series() , så du måste ta itu med det i din ansökan eller prova detta smarta hack .



  1. Hur man ställer in timeout för anslutning i SQLAlchemy

  2. Varför är IS NOT NULL falsk när man kontrollerar en radtyp?

  3. oinitierad konstant Mysql2::Client::SECURE_CONNECTION

  4. Återställ din WordPress-databas med WP-CLI