Трябва да поставите потребителската проверка в присъединяването, а не в условието where, като така:
SELECT c.course_id,l.topic,l.id,l.vid_duration,p.*
FROM courses c
LEFT JOIN lessons l ON l.course_id=c.course_id
LEFT JOIN progress p ON l.id = p.lesson_id and p.user_id = :userid
WHERE c.slug = :course
Причината да се направи това е, че JOINS използват "лявото присъединяване" (което е имплицитно външно присъединяване). Този тип свързване означава, че ако условието работи, връща всички данни от колоната за тази таблица за този ред.. ако цялото условието не работи, то ще върне всички данни за таблици, споменати по-рано, но за таблицата, спомената в реда, ще върне NULLS за всички тези колони.
Извинявам се за това описание, тъй като е трудно да се изрази с думи как точно работи сложното външно (или ляво) присъединяване, без да става дума за много думи.