sql >> Databáze >  >> RDS >> Mysql

MySQL seskupuje podle data a počtu včetně chybějících dat

Potřebujete OUTER JOIN dostat se na každý den mezi začátkem a koncem, protože pokud použijete INNER JOIN omezí výstup pouze na data, která jsou spojena (tj. pouze na data v tabulce přehledu).

Navíc, když použijete OUTER JOIN musíte dbát na splnění podmínek v where clause nezpůsobují implicit inner join; například AND domain_id =1 pokud by použití v klauzuli where potlačilo jakýkoli řádek, který tuto podmínku nesplnil, ale při použití jako podmínka spojení omezí pouze řádky tabulky sestavy.

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;

Také jsem změnil odvozenou tabulku all_dates pomocí DATE_ADD() abych posunul výchozí bod do budoucnosti, a zmenšil jsem jeho velikost. Obě tyto možnosti jsou možnosti a lze je upravit, jak uznáte za vhodné.

Ukázka na SQLfiddle

k dosažení id_domény pro každý řádek (jak je uvedeno ve vaší otázce) byste museli použít něco jako následující; Všimněte si, že můžete použít IFNULL() což je specifické pro MySQL, ale použil jsem COALESCE() což je obecnější SQL. Nicméně použití @parametru, jak je zde uvedeno, je každopádně specifické pro MySQL.

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;

Podívejte se na to na SQLfiddle



  1. Ovlivňují omezení cizích klíčů transformace dotazů v Oracle?

  2. Pořadí provádění podmínek v klauzuli SQL 'where'

  3. Jak vybrat dva sloupce jako jeden?

  4. Jak aktualizovat statistiky serveru SQL pro velké tabulky