My table is:
id | student_id | exam_date | license | result |
---|---|---|---|---|
1 | 101 | 01-11-2020 | B2 | FAILED |
2 | 102 | 15-11-2020 | A | PASSED |
3 | 103 | 22-11-2020 | D | FAILED |
4 | 101 | 01-10-2020 | D | PASSED |
5 | 104 | 01-12-2020 | A | PASSED |
6 | 103 | 29-11-2020 | D | PASSED |
7 | 101 | 01-12-2020 | B2 | PASSED |
8 | 105 | 01-09-2020 | B2 | FAILED |
9 | 104 | 01-11-2020 | A | FAILED |
10 | 105 | 01-11-2020 | B2 | PASSED |
I need to select the results that would have the first result according to the exam date according to each student id and the license column. If the same student takes different license exam, these two results need to come up as well. But I need only one result row for each student id and license value.
The result should look like this:
id | student_id | exam_date | license | result |
---|---|---|---|---|
1 | 101 | 01-11-2020 | B2 | FAILED |
2 | 102 | 15-11-2020 | A | PASSED |
3 | 103 | 22-11-2020 | D | FAILED |
4 | 101 | 01-10-2020 | D | PASSED |
8 | 105 | 01-09-2020 | B2 | FAILED |
9 | 104 | 01-11-2020 | A | FAILED |
I've done the research and queries and so far I only got 1 row for student_id although the student takes two different license examination.
The following is my query:
SELECT scct_outer.id, scct_outer.stud_id, scct_outer.exam_date, scct_outer.license, scct_outer.result
FROM stud_cdl_comp_test AS scct_outer
INNER JOIN
(SELECT stud_id, MIN(exam_date) AS MinExamDate
FROM stud_cdl_comp_test AS scct
INNER JOIN stud AS s ON scct.stud_id = s.id
INNER JOIN agent_profile AS ap ON s.agent_profile_id = ap.id
GROUP BY stud_id) groupedscct
ON scct_outer.stud_id = groupedscct.stud_id
AND scct_outer.exam_date = groupedscct.MinExamDate
Thinking that you are grouping by student_id in this case is almost incorrect in this case. What are actually grouping by is student + license. Let's call this key combination individual_license
.
Here's what the solution will look like:
SELECT
st.id,
st.stud_id,
st.exam_date,
st.license,
st.result
FROM stud_cdl_comp_test AS st
INNER JOIN
(SELECT
MIN(exam_date) AS min_date,
st_inner.student_id,
st_inner.license
FROM stud_cdl_comp_test AS st_inner
GROUP BY st_inner.student_id, st_inner.license
) grouped_inner
ON grouped_inner.student_id = st.student_id
AND grouped_inner.license = st.license
AND grouped_inner.min_date = st.exam_date;
This should work.
The problem with you original code is that it is missing a correlartion on the licences between the outer query and the subquery. You would phrase it as:
select s.*
from stud_cdl_comp_test s
inner join (
select student_id, licence, min(exam_date) as minexamdate
from stud_cdl_comp_test as scct
group by stud_id, licence
) s1 on s1.student_id = s.student_id and s1.license = s.license and s1.minexamdate = s.date
I have no idea what stud
and agent_profile
are, so I removed the from the query.
That said, this is not the method I would recommend - a simple and efficient option is to filter with a subquery:
select *
from stud_cdl_comp_test s
where s.exam_date = (
select min(s1.exam_date)
from stud_cdl_comp_test s1
where s1.student_id = s.student_id and s1.license = s.license
)
This can take advantage of an index on (student_id, license, exam_date)
.
Alternatively, you can use row_number()
, available in MySL 8.0:
select *
from (
select s.*,
row_number() over(partition by student_id, licence order by exam_date) rn
from stud_cdl_comp_test s
) s
where rn = 1
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.