First, the condition WHERE date_field >= (CURDATE()-INTERVAL 1 MONTH)
will not restrict your results to the current month. It will fetch all dates from 30-31 days ago up to the current date (and to the future, if there are rows with future dates in the table).
It should be:
WHERE date_field >= LAST_DAY(CURRENT_DATE) + INTERVAL 1 DAY - INTERVAL 1 MONTH
AND date_field < LAST_DAY(CURRENT_DATE) + INTERVAL 1 DAY
Now, to the main question, to create 28-31 dates, even if the table has not rows for all the dates, you could use a Calendar
table (with all dates, say for years 1900 to 2200) or create them on the fly, with something like this (the days
table can be either a temporary table or you can even make it a derived table, with a somewhat more complicated query than this one):
CREATE TABLE days
( d INT NOT NULL PRIMARY KEY ) ;
INSERT INTO days
VALUES (0), (1), (2), ....
..., (28), (29), (30) ;
SELECT
cal.my_date AS date_field,
COALESCE(t.val, 0) AS val
FROM
( SELECT
s.start_date + INTERVAL (days.d) DAY AS my_date
FROM
( SELECT LAST_DAY(CURRENT_DATE) + INTERVAL 1 DAY - INTERVAL 1 MONTH
AS start_date,
LAST_DAY(CURRENT_DATE)
AS end_date
) AS s
JOIN days
ON days.d <= DATEDIFF(s.end_date, s.start_date)
) AS cal
LEFT JOIN my_table AS t
ON t.date_field >= cal.my_date
AND t.date_field < cal.my_date + INTERVAL 1 DAY ;
The above should work for any type of the date_field
column (date, datetime, timestamp). If the date_field
column is of type DATE
, the last join can be simplified to:
LEFT JOIN my_table AS t
ON t.date_field = cal.my_date ;
The easiest way is to have a calendar
table, defined in the following way:
CREATE TABLE calendar
(
a_day date PRIMARY KEY
) ;
... and filled with all the relevant dates (i.e.: all days from 1990-1-1 to 2100-12-31). For the sake of simplicity, we will fill it only with year 2013:
INSERT INTO
calendar (a_day)
VALUES
('2013-01-01'),
('2013-01-02'),
('2013-01-03'),
('2013-01-04'),
('2013-01-05'),
-- everything up to
('2013-12-31') ;
At this point, you can just have a JOIN
with the two tables; with the join condition not being an equality, but a range condition:
SELECT
t.id, c.a_day
FROM
t
JOIN calendar c ON c.a_day BETWEEN t.start_date AND t.end_date
ORDER BY
t.id, c.a_day ;
... and get
id | a_day
-: | :---------
1 | 2013-01-14
1 | 2013-01-15
1 | 2013-01-16
1 | 2013-01-17
1 | 2013-01-18
2 | 2013-02-01
2 | 2013-02-02
2 | 2013-02-03
2 | 2013-02-04
You can see all the setup at dbfiddle here
Best Answer
You can use the BETWEEN conditional operator to search for anything in a range. The BETWEEN operater is inclusive so will find records for the start and end dates too.
You will be able to query the
attendance
table directly:SELECT * FROM attendance WHERE attendancedate BETWEEN '2019-04-03' AND '2019-06-03'
This question has some examples: https://stackoverflow.com/questions/3822648/how-do-i-query-between-two-dates-using-mysql
I hope that helps!