Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL-Gruppierung nach Datum und Anzahl einschließlich fehlender Daten

Sie benötigen einen OUTER JOIN um jeden Tag zwischen einem Anfang und einem Ende anzukommen, denn wenn Sie einen INNER JOIN verwenden Dadurch wird die Ausgabe auf die verknüpften Daten beschränkt (d. h. nur auf die Daten in der Berichtstabelle).

Außerdem, wenn Sie einen OUTER JOIN verwenden Sie müssen auf Bedingungen in der where clause achten verursachen keinen implicit inner join; zum Beispiel UND domain_id =1 if-Verwendung in der where-Klausel würde jede Zeile unterdrücken, die diese Bedingung nicht erfüllt, aber wenn sie als Join-Bedingung verwendet wird, schränkt sie nur die Zeilen der Berichtstabelle ein.

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;

Ich habe auch die abgeleitete Tabelle all_dates geändert, indem ich DATE_ADD() verwendet habe um den Ausgangspunkt in die Zukunft zu verschieben, und ich habe die Größe reduziert. Beides sind Optionen und können nach Belieben angepasst werden.

Demo bei SQLfiddle

um zu einer domain_id für jede Zeile zu gelangen (wie in Ihrer Frage gezeigt), müssten Sie etwas wie das Folgende verwenden; Beachten Sie, dass Sie IFNULL() verwenden könnten Das ist MySQL-spezifisch, aber ich habe COALESCE() verwendet das ist allgemeineres SQL. Die Verwendung eines @-Parameters, wie hier gezeigt, ist jedoch ohnehin MySQL-spezifisch.

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;

Siehe dies bei SQLfiddle