繁体   English   中英

如何在 SQL 中将 SELECT 行与 MIN(DateTime 列)、另一列分组和另一列 DISTINCT?

[英]How to SELECT rows with MIN(DateTime column), GROUP by another column and DISTINCT by another column in SQL?

我的桌子是:

ID 学生卡 考试日期 执照 结果
1 101 01-11-2020 B2 失败的
2 102 15-11-2020 一个 通过
3 103 22-11-2020 D 失败的
4 101 01-10-2020 D 通过
5 104 01-12-2020 一个 通过
6 103 29-11-2020 D 通过
7 101 01-12-2020 B2 通过
8 105 01-09-2020 B2 失败的
9 104 01-11-2020 一个 失败的
10 105 01-11-2020 B2 通过

我需要 select 根据每个学生 ID 和许可证列,根据考试日期获得第一个结果的结果。 如果同一个学生参加不同的执照考试,这两个结果也需要拿出来。 但是对于每个学生 ID 和许可证值,我只需要一个结果行。

结果应如下所示:

ID 学生卡 考试日期 执照 结果
1 101 01-11-2020 B2 失败的
2 102 15-11-2020 一个 通过
3 103 22-11-2020 D 失败的
4 101 01-10-2020 D 通过
8 105 01-09-2020 B2 失败的
9 104 01-11-2020 一个 失败的

我已经完成了研究和查询,到目前为止,尽管学生参加了两次不同的执照考试,但我只得到了 1 行的 student_id。

以下是我的查询:

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

在这种情况下,认为您在这种情况下按 student_id 分组几乎是不正确的。 实际上分组的是学生+许可证。 我们称这个组合键为individual_license

解决方案如下所示:

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;

这应该有效。

您的原始代码的问题是它缺少外部查询和子查询之间的许可证相关性。 您可以将其表述为:

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

我不知道studagent_profile是什么,所以我从查询中删除了。

也就是说,这不是我推荐的方法 - 一个简单而有效的选择是使用子查询进行过滤:

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
)

这可以利用(student_id, license, exam_date)上的索引。

或者,您可以使用 MySL 8.0 中提供的row_number()

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM