Você precisa de um
OUTER JOIN
para chegar todos os dias entre um início e um fim, porque se você usar um INNER JOIN
ele restringirá a saída apenas às datas que são unidas (ou seja, apenas as datas na tabela do relatório). Além disso, quando você usa um
OUTER JOIN
você deve tomar cuidado para que as condições na where clause
não cause uma implicit inner join
; por exemplo AND domain_id =1 se o uso na cláusula where suprimiria qualquer linha que não tivesse essa condição atendida, mas quando usado como uma condição de junção, restringiria apenas as linhas da tabela do relatório. 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;
Também alterei a tabela derivada all_dates, usando
DATE_ADD()
para empurrar o ponto de partida para o futuro, e reduzi o seu tamanho. Ambas são opções e podem ser ajustadas como você achar melhor. Demonstração no SQLfiddle
para chegar a um domain_id para cada linha (como mostrado em sua pergunta), você precisaria usar algo como o seguinte; Observe que você pode usar
IFNULL()
que é específico do MySQL, mas eu usei COALESCE()
que é SQL mais genérico. No entanto, o uso de um @parameter como mostrado aqui é específico do MySQL de qualquer maneira. 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;
Veja isso em SQLfiddle