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

MySQL-grupper efter dato og antal inklusive manglende datoer

Du skal bruge en OUTER JOIN at ankomme hver dag mellem start og slut, fordi hvis du bruger en INNER JOIN det vil begrænse output til kun de datoer, der er sammenføjet (dvs. kun disse datoer i rapporttabellen).

Derudover, når du bruger en OUTER JOIN du skal passe på, at betingelserne i where clause forårsager ikke en implicit inner join; for eksempel AND domain_id =1 hvis brug i where-sætningen ville undertrykke enhver række, der ikke havde denne betingelse opfyldt, men når den bruges som en join-betingelse, begrænser den kun rækkerne i rapporttabellen.

SELECT
      COUNT(r.domain_id)
    , all_dates.Date AS the_date
    , domain_id
FROM (
        SELECT DATE_ADD(curdate(), INTERVAL 2 MONTH) - INTERVAL (a.a + (10 * b.a) ) DAY as Date
        FROM (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
        CROSS JOIN (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
      ) all_dates
      LEFT OUTER JOIN reports r
                  ON all_dates.Date = r.tracked_on
                        AND domain_id = 1
WHERE all_dates.Date BETWEEN '2014-09-01' AND '2014-09-30'
GROUP BY
      the_date
ORDER BY
      the_date ASC;

Jeg har også ændret tabellen med alle_datoer ved at bruge DATE_ADD() at skubbe udgangspunktet ind i fremtiden, og jeg har reduceret dens størrelse. Begge disse er muligheder og kan justeres, som du finder passende.

Demo på SQLfiddle

for at nå frem til et domæne_id for hver række (som vist i dit spørgsmål) skal du bruge noget som det følgende; Bemærk, at du kan bruge IFNULL() som er MySQL-specifik, men jeg har brugt COALESCE() som er mere generisk SQL. Men brugen af ​​en @parameter som vist her er MySQL-specifik alligevel.

SET @domain := 1;

SELECT
      COUNT(r.domain_id)
    , all_dates.Date AS the_date
    , coalesce(domain_id,@domain) AS domain_id
FROM (
        SELECT DATE_ADD(curdate(), INTERVAL 2 month) - INTERVAL (a.a + (10 * b.a) ) DAY as Date
        FROM (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
        CROSS JOIN (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
      ) all_dates
      LEFT JOIN reports r
                  ON all_dates.Date = r.tracked_on
                        AND domain_id = @domain
WHERE all_dates.Date BETWEEN '2014-09-01' AND '2014-09-30'
GROUP BY
      the_date
ORDER BY
      the_date ASC;

Se dette på SQLfiddle



  1. Opdater flere kolonner i SQL

  2. Fix Msg 8117 "Operand data type varchar er ugyldig for sum operator" i SQL Server

  3. Returner 0, hvis feltet er null i MySQL

  4. PostgreSQL krydstabulatorforespørgsel