Anda harus menempatkan cek pengguna di gabung, bukan di tempat seperti kondisi:
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
Alasan untuk melakukan ini adalah bahwa GABUNG menggunakan "gabung kiri" (yang secara implisit merupakan gabungan luar". Jenis gabungan ini berarti bahwa jika kondisinya berhasil, kembalikan semua data kolom untuk tabel itu untuk baris itu.. jika keseluruhan kondisi tidak bekerja, itu akan mengembalikan semua data untuk tabel yang disebutkan sebelumnya, tetapi untuk tabel yang disebutkan di baris, itu akan mengembalikan NULLS untuk semua kolom tersebut.
Saya mohon maaf atas deskripsi tersebut, karena sulit untuk menjelaskan dengan tepat bagaimana gabungan luar (atau kiri) yang kompleks bekerja tanpa bertele-tele.