这种问题我自己归纳为“找对应行”问题,例如有下面一场表(学生做题,对每个知识点的得分情况)
最高分、最低分
对应的知识点名称最后一次没有学习
对应的知识点名称由此我们可以看出:
(在MySQL8.0之后还可以通过窗口函数来解决)
select user_id , max(score) ... group by user_id
select a.user_id, knowledge_name as goodfrom tb as ajoin (select user_id, max(score) as maxfrom tbgroup by user_id) as bon a.user_id = b.user_id and a.score = b.maxgroup by a.user_id
我们在join联表的同时,对A(分组)和B(筛选条件)在on后面进行界定
因此我们使用了JOIN后跟子查询,而不是where后跟子查询
上面这种SQL有个问题,就是如果有多个并列最高的score,那查出来的顺序是谁?
默认情况下的升序asc,null值是全部排在最顶行
降序desc,null值全部在最下面
我们可以手动制定MySQL排序null的位置来调整,当然本案例中没影响
如果两个数据都是score = 100,则取的是扫描到的第一行
现在场景换成了:user_id、当天的point数量、当天达标的point数量、当天score最高对应的知识点、当天score最低对应的知识点
要同时在查询出来的那一行求出“最大值、最小值”对应的那行数据,按道理我们可以写两次子查询然后join两次(5.7的写法),但在MySQL8.0可以有更简洁的first_value()、last_value()
窗口函数(窗口函数详细内容见另一篇《MySQL窗口函数》)
这里直接demo对比下二者在实际场景中的的写法
很难看