To do this, you need an existence of a record per each date. Since this is not the case in your submitted_changes
table - I'll suggest to create a date table (if you don't have it already).
Note - for the shortest version, check the last edit at the bottom:
Here is an example with a temporary table. First run:
CREATE TEMPORARY TABLE IF NOT EXISTS dates AS
SELECT DATE(curdate()-num) as date_col
FROM
(
SELECT 0 as num
UNION
SELECT 1
UNION
SELECT 2
UNION
SELECT 3
UNION
SELECT 4
UNION
SELECT 5
UNION
SELECT 6) sub
This will create a table with 7 relevant dates.
Now left join
it with your data:
SELECT
count(Distinct name) as total,
DATE_FORMAT(date_col, '%M %d, %Y') AS date_added
FROM dates LEFT JOIN submitted_changes
on (dates.date_col = DATE(submitted_changes.date_added))
GROUP BY date_col
You can also run it as a one-shot query (with no create
statement):
SELECT
count(Distinct name) as total,
DATE_FORMAT(date_col, '%M %d, %Y') AS date_added
FROM
(SELECT DATE(curdate()-num) as date_col
FROM
(
SELECT 0 as num
UNION
SELECT 1
UNION
SELECT 2
UNION
SELECT 3
UNION
SELECT 4
UNION
SELECT 5
UNION
SELECT 6) sub) dates
LEFT JOIN submitted_changes
on (dates.date_col = DATE(submitted_changes.date_added))
GROUP BY date_col
Another approach is a permanent dim_date
. Here is a sample code for static table (with more extra fields):
CREATE TABLE dim_date (
id int(11) NOT NULL AUTO_INCREMENT,
date date,
day int(11),
month int(11),
year int(11),
day_name varchar(45),
PRIMARY KEY (id),
INDEX date_index (date)
)
and then populate it:
SET @currdate := "2015-01-01";
SET @enddate := "2025-01-01";
delimiter $$
DROP PROCEDURE IF EXISTS BuildDate$$
CREATE PROCEDURE BuildDate()
BEGIN
WHILE @currdate < @enddate DO
INSERT INTO dim_date (date, day, month, year, day_name)
VALUES (
@currdate, DAY(@currdate), MONTH(@currdate),
YEAR(@currdate), DAYNAME(@currdate)
);
SET @currdate := DATE_ADD(@currdate, INTERVAL 1 DAY);
END WHILE;
END$$
CALL BuildDate();
Then you can finally run your query with a left join
:
SELECT
count(Distinct name) as total,
DATE_FORMAT(date, '%M %d, %Y') AS date_added
FROM dim_date LEFT JOIN submitted_changes
on (dim_date.date = DATE(submitted_changes.date_added))
WHERE date >= NOW() - INTERVAL 1 WEEK
GROUP BY date
This would return a line per each date, even if there are no records in submitted_changes
for them.
Edit: another one-shot super short version inspired by this post:
SELECT
count(Distinct name) as total,
DATE_FORMAT(date, '%M %d, %Y') AS date_added
(SELECT date(curdate()-id%7) as date
FROM submitted_changes
GROUP BY num) dates LEFT JOIN submitted_changes
on (date.dates = DATE(submitted_changes.date_added))
GROUP BY date