I've a mysql table with me
Now we want to do some calculations like this
Expected output where we calculate all courses enrolled
Expected output where we calculate all courses enrolled where course id = 2
expected output where course_id = 2 AND date range is between 2022-11-15 to 2022-11-13
The query which I've right now
SELECT COUNT(*), DATE(registered_on)
FROM courses_enrolled
WHERE course_id = 1
GROUP BY DATE(registered_on), course_id
ORDER BY registered_on desc;
You need to use some kind of calendar table approach here:
SELECT d.dt AS date, COUNT(ce.id) AS cnt
FROM (
SELECT '2022-11-12' AS dt UNION ALL
SELECT '2022-11-13' UNION ALL
SELECT '2022-11-14' UNION ALL
SELECT '2022-11-15'
) d
LEFT JOIN courses_enrolled ce
ON DATE(ce.registered_on) = d.dt AND
ce.course_id = 2
GROUP BY d.dt
ORDER BY d.dt;
The calendar table ensures that all dates you want in the output appear. In practice, you may replace the subquery in d
with a bona-fide table containing all dates of interest. The left join ensures that no dates are dropped which have no matching courses on that day.
If you are using MySQL 8 you can use a recursive CTE to create your date range.
For all enrolled courses for given date range -
WITH RECURSIVE calendar (date) AS (
SELECT '2022-11-13' # start date
UNION ALL
SELECT date + INTERVAL 1 DAY FROM calendar
WHERE date + INTERVAL 1 DAY <= '2022-11-15' # end date
)
SELECT COUNT(ce.id) count_all, c.date
FROM calendar c
LEFT JOIN courses_enrolled ce
ON ce.registered_on BETWEEN c.date AND (c.date + INTERVAL 1 DAY - INTERVAL 1 SECOND)
GROUP BY c.date
ORDER BY c.date DESC;
Note the use of BETWEEN start AND end of day in the join criteria. For a small dataset this offers negligible benefit but on a large dataset it would allow for use of an index on registered_on
, which could offer significantly improved performance.
Or for just the selected course -
WITH RECURSIVE calendar (date) AS (
SELECT '2022-11-13' # start date
UNION ALL
SELECT date + INTERVAL 1 DAY FROM calendar
WHERE date + INTERVAL 1 DAY <= '2022-11-15' # end date
)
SELECT COUNT(ce.id) count_selected_course, c.date
FROM calendar c
LEFT JOIN courses_enrolled ce
ON ce.registered_on BETWEEN c.date AND (c.date + INTERVAL 1 DAY - INTERVAL 1 SECOND)
AND ce.course_id = 2
GROUP BY c.date
ORDER BY c.date DESC;
Or counting both at the same time -
WITH RECURSIVE calendar (date) AS (
SELECT '2022-11-13' # start date
UNION ALL
SELECT date + INTERVAL 1 DAY FROM calendar
WHERE date + INTERVAL 1 DAY <= '2022-11-15' # end date
)
SELECT COUNT(ce.id) count_all, COUNT(IF(ce.course_id = 2, ce.id, NULL)) count_selected_course, c.date
FROM calendar c
LEFT JOIN courses_enrolled ce
ON ce.registered_on BETWEEN c.date AND (c.date + INTERVAL 1 DAY - INTERVAL 1 SECOND)
GROUP BY c.date
ORDER BY c.date DESC;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.