之前也做了很多SQL题目,但是都没有实际运行过,最近建表和查询一步步亲身实践才发现了很多基础的问题还没有理解透彻。所以动手的确还是第一重要的。
通过case when也让我对group by和聚合函数的使用有了更深一步的理解。
其实这里主要涉及到的问题和case when没有实质性的关系。
原数据:
加了max实现的行转列
不加max实现的行转列:
这里可以在看一下不加group by的情况:
这里就可以看到,先执行出来表三,然后进行分组groupby,group by没有任何聚合函数,所以会从基表里取group by后字段的第一条数据,
也就是表一执行的结果。
那么下面来说一哈第二个使用max聚合的正确结果。就是先用聚合取出来最大分数,然后再对姓名进行分组。所以会取到每个姓名下每个学科的最高成绩。再按姓名进行分组。
还有另外的解释:
按照SQL查询执行的顺序,先按照名字分组,然后第一个语文符合条件,成绩可以正确出来,但是遇到数学的时候,第一个case不是语文,所以取0。
但是按照max写法,遇到数学的时候是0但是会继续执行第二个case,这时是83,取两个最大的,然后执行第三个case 是0,所以数学取83.
看到大佬们分析到这里对为什么要加max有了更加具体的了解,是因为分组函数导致的,与case when没有很大关系,分组函数一定要和聚合函数一同存在。
比如上述数据,按照名字分组之后,每个组内有三个数据,而展示的时候就只展示一条,所以必须从中选择一条展示所以才出现了上述数据不完全正确的状况,所以在使用分组函数的同时一定要使用聚合函数,
分组select的基本格式:
select [聚合函数] 字段名 from tablename
[where]
[group by] 字段名
[having]
group by 子句:
根据给定列或者表达式的每一个不同的值将表中的行分成不同的组,使用组函数返回每一组的统计信息。
规则:
1、出现在select子句中的单独的列,必须出现在group by子句中作为分组列。
2、分组列可以不出现在select子句当中。
3、分组列可以出现在select子句中的一个符合表达式中。
4、如果group by后面是一个复合表达式,那么在select子句中,必须整体作为一个表达式的一部分才能使用。
对于第一条的解释:
举个栗子:
如果是出现在group by子句中的字段,当我们去select时,它的列值是唯一的。比如
这个是按照姓名分组的,我们去select姓名,数据库会选择按照姓名分组后的一条记录显示,因为我们就是按照姓名分组的所以选择任何一条数据的姓名列值是相同的,比如图中的‘zhangsan’ 但是为什么不出现在group by子句中的字段不能选择呢,比如 语文 数学字段,因为他们的记录值可能是不一样的,但是显示的时候只能取一条,所以取到的值可能正确也可能不正确,可能是0也可能是83。