A set of queries with a sequential approximation to the result
create table `lesson` ( `id` int, `id_course` int, `lesson_title` text );
create table history ( `id` int, `id_lesson` int, `email` text, `date` date );
Insert into `lesson` (`id`,`id_course`,`lesson_title`) values (1, 3, 'Урок 1'), (2, 3, 'Урок 2'), (3, 3, 'Урок 3'), (4, 4, 'Урок 4'), (5, 4, 'Урок 5') ;
Insert into `history` (`id`,`id_lesson`,`email`,`date`) values (43, 1, '100@gmail.com', '2018-07-10'), (44, 2, '100@gmail.com', '2018-07-11'), (45, 3, '100@gmail.com', '2018-07-12'), (46, 4, '110@gmail.com', '2018-07-13'), (47, 5, '110@gmail.com', '2018-07-14'), (48, 1, '200@gmail.com', '2018-07-15'), (49, 2, '200@gmail.com', '2018-07-16'), (50, 1, '300@gmail.com', '2018-07-17'), (51, 4, '300@gmail.com', '2018-07-18') ;
select * from `lesson`;
id | id_course | lesson_title
-: | --------: | : -----------
1 | 3 | Lesson 1
2 | 3 | Lesson 2
3 | 3 | Lesson 3
4 | 4 | Lesson 4
5 | 4 | Lesson 5
select * from `history`;
id | id_lesson | email | date
-: | --------: | : ------------ | : ---------
43 | 1 | 100@gmail.com | 2018-07-10
44 | 2 | 100@gmail.com | 2018-07-11
45 | 3 | 100@gmail.com | 2018-07-12
46 | 4 | 110@gmail.com | 2018-07-13
47 | 5 | 110@gmail.com | 2018-07-14
48 | 1 | 200@gmail.com | 2018-07-15
49 | 2 | 200@gmail.com | 2018-07-16
50 | 1 | 300@gmail.com | 2018-07-17
51 | 4 | 300@gmail.com | 2018-07-18
Get courses that the student took
select distinct h.`email`, l.`id_course` from `lesson` l join `history` h on l.`id` = h.`id_lesson`
email | id_course
: ------------ | --------:
100@gmail.com | 3
110@gmail.com | four
200@gmail.com | 3
300@gmail.com | 3
300@gmail.com | four
Get a full list of classes that a student must take to complete the courses (but not all the classes the student has passed, for example 200@gmail.com did not complete 3 lessons 3)
select cr.`email`, cr.`id_course`, L0.`id` as id_lesson from ( select distinct h.`email`, L.`id_course` from `lesson` L join `history` h on L.`id` = h.`id_lesson` ) as cr join `lesson` L0 on cr.`id_course` = L0.`id_course` order by cr.`email` asc, cr.`id_course` asc, L0.`id` asc
email | id_course | id_lesson
: ------------ | --------: | --------:
100@gmail.com | 3 | one
100@gmail.com | 3 | 2
100@gmail.com | 3 | 3
110@gmail.com | 4 | four
110@gmail.com | 4 | five
200@gmail.com | 3 | one
200@gmail.com | 3 | 2
200@gmail.com | 3 | 3
300@gmail.com | 3 | one
300@gmail.com | 3 | 2
300@gmail.com | 3 | 3
300@gmail.com | 4 | four
300@gmail.com | 4 | five
Real table of passing / failing classes (lessons)
-- полная таблица прохождения/непрохождения уроков select L1.`email`, L1.`id_course`, L1.`id_lesson`, H1.`email` from ( select cr.`email`, cr.`id_course`, L0.`id` as id_lesson from ( select distinct h.`email`, L.`id_course` from `lesson` L join `history` h on L.`id` = h.`id_lesson` ) as cr join `lesson` L0 on cr.`id_course` = L0.`id_course` ) L1 left outer join `history` H1 on H1.`email` = L1.`email` and H1.`id_lesson` = L1.`id_lesson` order BY L1.`email`, L1.`id_course`, L1.`id_lesson`
email | id_course | id_lesson | email
: ------------ | --------: | --------: | : ------------
100@gmail.com | 3 | 1 | 100@gmail.com
100@gmail.com | 3 | 2 | 100@gmail.com
100@gmail.com | 3 | 3 | 100@gmail.com
110@gmail.com | 4 | 4 | 110@gmail.com
110@gmail.com | 4 | 5 | 110@gmail.com
200@gmail.com | 3 | 1 | 200@gmail.com
200@gmail.com | 3 | 2 | 200@gmail.com
200@gmail.com | 3 | 3 | null
300@gmail.com | 3 | 1 | 300@gmail.com
300@gmail.com | 3 | 2 | null
300@gmail.com | 3 | 3 | null
300@gmail.com | 4 | 4 | 300@gmail.com
300@gmail.com | 4 | 5 | null
Choosing who failed the course
-- ученик не прошел весь курс select distinct L1.`email`, L1.`id_course` from ( select cr.`email`, cr.`id_course`, L0.`id` as id_lesson from ( select distinct h.`email`, L.`id_course` from `lesson` L join `history` h on L.`id` = h.`id_lesson` ) as cr join `lesson` L0 on cr.`id_course` = L0.`id_course` ) L1 left outer join `history` H1 on H1.`email` = L1.`email` and H1.`id_lesson` = L1.`id_lesson` where H1.`email` is null
email | id_course
: ------------ | --------:
300@gmail.com | 3
200@gmail.com | 3
300@gmail.com | four
We get the dates of the last classes of courses that the student took
select h.`email`, L.`id_course`, max(h.`date`) as `max_date` from `lesson` L join `history` h on L.`id` = h.`id_lesson` group by h.`email`, L.`id_course`
email | id_course | max_date
: ------------ | --------: | : ---------
100@gmail.com | 3 | 2018-07-12
110@gmail.com | 4 | 2018-07-14
200@gmail.com | 3 | 2018-07-16
300@gmail.com | 3 | 2018-07-17
300@gmail.com | 4 | 2018-07-18
RESULT: users past the course
-- РЕЗУЛЬТАТ: пользователи прошедшие курс select L3.`email`, L3.`id_course`, T07.`max_date` from ( select distinct h.`email`, l.`id_course` from `lesson` l join `history` h on l.`id` = h.`id_lesson` ) L3 left outer join ( select distinct L1.`email`, L1.`id_course` from ( select cr.`email`, cr.`id_course`, L0.`id` as id_lesson from ( select distinct h.`email`, L.`id_course` from `lesson` L join `history` h on L.`id` = h.`id_lesson` ) as cr join `lesson` L0 on cr.`id_course` = L0.`id_course` ) L1 left outer join `history` H1 on H1.`email` = L1.`email` and H1.`id_lesson` = L1.`id_lesson` where H1.`email` is null ) L2 on L2.`email` = L3.`email` and L2.`id_course` = L3.`id_course` join ( select h.`email`, L.`id_course`, max(h.`date`) as `max_date` from `lesson` L join `history` h on L.`id` = h.`id_lesson` group by h.`email`, L.`id_course` ) as T07 on T07.`email` = L3.`email` and T07.`id_course` = L3.`id_course` where L2.`email` is null and L3.`id_course` = 4 -- Ограничиваем одним курсом ;
email | id_course | max_date
: ------------ | --------: | : ---------
110@gmail.com | 4 | 2018-07-14
db <> fiddle here