I have this query:
SELECT
`sr`.`transactionDate`,
`b`.`title`,
`b`.`color`,
ROUND(SUM(sr.digitalEarnings), 2) AS earnings
FROM
`sales_report` AS `sr`
INNER JOIN `sales_source` AS `ss` ON `sr`.`salesSourceId` = `ss`.`id`
INNER JOIN `book` AS `b` ON `ss`.`bookId` = `b`.`id`
LEFT JOIN `series` AS `s` ON `b`.`seriesId` = `s`.`id`
GROUP BY `ss`.`bookId` , `sr`.`transactionDate`
ORDER BY 4 DESC;
Instead of only returning data for the days which exist in sales_report
, I need one row per day, per b.title
between 2 dates.
So if I queried for January, I'd have 31 entries for one book with zero earnings
on the days which have no entries in sales_report
.
I'm assuming left joining on a fake table with all the dates in or something like that might be the route to go down but I can't get my head around it.
Is this possible purely with mysql?
p.s My SQL query is dynamically generated in code so if a left join on a bunch of "generated data" is the way to go, this is an option. This is the avenue I'm currently exploring.
Edit: The question is similar to Results for every hour of the day even data if not present but this one is for SQL and I'd prefer to not use a temp table.
Edit:
I've just tried this:
SELECT
lj.gh,
`sr`.`transactionDate`,
`b`.`title`,
`b`.`color`,
ROUND(SUM(sr.digitalEarnings), 2) AS earnings
FROM
(
select gen_date as gh from
(select adddate('1970-01-01',t4*10000 + t3*1000 + t2*100 + t1*10 + t0) gen_date from
(select 0 t0 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,
(select 0 t1 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1,
(select 0 t2 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2,
(select 0 t3 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3,
(select 0 t4 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4) v
where gen_date between '2017-01-01' and '2017-01-31'
) as lj
left join `sales_report` AS `sr` on sr.transactionDate = lj.gh
INNER JOIN `sales_source` AS `ss` ON `sr`.`salesSourceId` = `ss`.`id`
INNER JOIN `book` AS `b` ON `ss`.`bookId` = `b`.`id`
LEFT JOIN `series` AS `s` ON `b`.`seriesId` = `s`.`id`
GROUP BY `ss`.`bookId` , `sr`.`transactionDate`, lj.gh
ORDER BY 1, b.title asc;
But I'm not quite seeing an entry per day for some reason...
Ah: Its returning each book (even if no sales_report) but only when there is at least one entry of sales_report
on that day which is down to the inner joins.
seq_0_to_99999
to do that crossjoin. In MySQL, I recommend building a table once and using it as needed.