每个学生最好成绩的科目
1 | CREATE TABLE `course` ( |
1 | select * from course; |
| student | course | score |
|---|---|---|
| 王五 | 语文 | 89 |
| 王五 | 数学 | 136 |
| 王五 | 理综 | 130 |
| 王五 | 英语 | 92 |
| 张三 | 英语 | 110 |
| 张三 | 数学 | 110 |
| 张三 | 语文 | 110 |
| 张三 | 理综 | 110 |
| 李四 | 理综 | 109 |
| 李四 | 语文 | 120 |
| 李四 | 数学 | 100 |
| 李四 | 英语 | 120 |
求每个学生成绩最好的科目
可能成绩最好的科目,分数一样
1 | SELECT m.student, m.max_score, c.course |
| student | max_score | course |
|---|---|---|
| 王五 | 136 | 数学 |
| 张三 | 110 | 英语 |
| 张三 | 110 | 数学 |
| 张三 | 110 | 语文 |
| 张三 | 110 | 理综 |
| 李四 | 120 | 语文 |
| 李四 | 120 | 英语 |
行列转换
样例数据准备
1 | create database sql_case; |
多行转多列
1 | select * from t1 |
| fyear | fdept | fscore |
|---|---|---|
| 2014 | B | 9 |
| 2015 | A | 8 |
| 2014 | A | 10 |
| 2015 | B | 7 |
求每年各部门的分数
1 | SELECT |
| fyear | fdept_a | fdept_b |
|---|---|---|
| 2014 | 10 | 9 |
| 2015 | 8 | 7 |
one more thing
错误写法
1 | SELECT |
报错
1 | (1055, "Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'sql_case.t1.fdept' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by") |
对于GROUP BY聚合操作,如果在SELECT中的列,没有在GROUP BY中出现,那么这个SQL是不合法的,因为列不在GROUP BY从句中,也就是说查出来的列必须在group by后面出现否则就会报错,或者这个字段出现在聚合函数里面。
只选择出现在group by后面的列,或者给列增加聚合函数
如何关闭ONLY_FULL_GROUP_BY选项?
服务级别(重启Mysql服务):
1 | set @@GLOBAL.sql_mode=''; |
全局配置:
在 [mysqld]和[mysql]下添加
1 | sql_mode ='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'; |
2. 多列转多行
问题描述:将问题一的结果转成源表,问题一结果表名为t1_2
1 | create table t1_2 |
1 | select * from t1_2; |
| fyear | fdept_a | fdept_b |
|---|---|---|
| 2014 | 10 | 9 |
| 2015 | 8 | 7 |
答案
1 | SELECT fyear, fdept, fscore |
| fyear | fdept | fscore |
|---|---|---|
| 2014 | A | 10 |
| 2015 | A | 8 |
| 2014 | B | 9 |
| 2015 | B | 7 |
3. 同一部门有多个绩效情况下,多行转多列
2014年公司组织架构调整,导致部门出现多个绩效,业务及人员不同,无法合并算绩效
1 | CREATE TABLE t1_3 LIKE t1; |
| fyear | fdept | fscore |
|---|---|---|
| 2014 | B | 9 |
| 2015 | A | 8 |
| 2014 | A | 10 |
| 2015 | B | 7 |
| 2014 | B | 6 |
1 | SELECT |
| fyear | fdept | fscore |
|---|---|---|
| 2014 | A | 10 |
| 2014 | B | 9,6 |
| 2015 | A | 8 |
| 2015 | B | 7 |
1 | SELECT |
| fyear | fdept_a | fdept_b |
|---|---|---|
| 2014 | 10 | 6,9 |
| 2015 | 8 | 7 |
排名中取他值
1 | create table t2 like t1; |
1 | select * from t2; |
| fyear | fdept | fscore |
|---|---|---|
| 2014 | A | 3 |
| 2014 | B | 1 |
| 2014 | C | 2 |
| 2015 | A | 4 |
| 2015 | D | 3 |
按a分组取b字段最小时对应的c字段
1 | select |
| fyear | fdept | fscore | rn |
|---|---|---|---|
| 2014 | A | 3 | 1 |
| 2014 | B | 1 | 2 |
| 2014 | C | 2 | 3 |
| 2015 | A | 4 | 1 |
| 2015 | D | 3 | 2 |
1 | select |
| fyear | fscore_of_min_fdept |
|---|---|
| 2014 | 3 |
| 2015 | 4 |
按a分组取b字段排第二时对应的c字段
1 | select |
| fyear | fscore_of_sec_min_fdept |
|---|---|
| 2014 | 1 |
| 2015 | 3 |
按a分组取b字段最小和最大时对应的c字段
1 | select |
| fyear | fdept | fscore | rn_asc | rn_desc |
|---|---|---|---|---|
| 2014 | C | 2 | 3 | 1 |
| 2014 | B | 1 | 2 | 2 |
| 2014 | A | 3 | 1 | 3 |
| 2015 | D | 3 | 2 | 1 |
| 2015 | A | 4 | 1 | 2 |
1 | select |
| fyear | fscore_of_min_dept | fscore_of_max_dept |
|---|---|---|
| 2014 | 3 | 2 |
| 2015 | 4 | 3 |
按a分组取b字段第二小和第二大时对应的c字段
1 | select |
| fyear | score_of_second_min_dept | score_of_second_max_dept |
|---|---|---|
| 2014 | 1 | 1 |
| 2015 | 3 | 4 |
按a分组取b字段前两小和前两大时对应的c字段
需保持fdept字段最小、最大排首位
1 | select |
| year | score_of_less_2_min_dept | score_of_less_2_max_dept |
|---|---|---|
| 2014 | 3,1 | 2,1 |
| 2015 | 4,3 | 3,4 |
累计求值
1 | create table t3 like t1; |
| fyear | fdept | fscore |
|---|---|---|
| 2015 | A | 4 |
| 2014 | A | 3 |
| 2014 | C | 2 |
| 2014 | B | 1 |
| 2015 | D | 3 |
按a分组按b字段排序,对c累计求和
1 | select |
| fyear | fdept | fscore | accu_sum_score |
|---|---|---|---|
| 2014 | A | 3 | 3 |
| 2014 | B | 1 | 4 |
| 2014 | C | 2 | 6 |
| 2015 | A | 4 | 4 |
| 2015 | D | 3 | 7 |
按a分组按b字段排序,对c取累计平均值
1 | select |
| fyear | fdept | fscore | accu_avg_score |
|---|---|---|---|
| 2014 | A | 3 | 3.0000 |
| 2014 | B | 1 | 2.0000 |
| 2014 | C | 2 | 2.0000 |
| 2015 | A | 4 | 4.0000 |
| 2015 | D | 3 | 3.5000 |
按a分组按b字段排序,对b取累计排名比例
1 | select |
| year | dept | score | accu_avg_score |
|---|---|---|---|
| 2014 | A | 3 | 0.33 |
| 2014 | B | 1 | 0.67 |
| 2014 | C | 2 | 1.00 |
| 2015 | A | 4 | 0.50 |
| 2015 | D | 3 | 1.00 |
按a分组按b字段排序,对b取累计求和比例
1 | select |
| year | dept | score | accu_ratio_score |
|---|---|---|---|
| 2014 | A | 3 | 0.17 |
| 2014 | B | 1 | 0.33 |
| 2014 | C | 2 | 0.50 |
| 2015 | A | 4 | 0.14 |
| 2015 | D | 3 | 0.29 |
窗口大小控制
1 | create table t4 like t1; |
| fyear | fdept | fscore |
|---|---|---|
| 2014 | A | 3 |
| 2014 | B | 1 |
| 2014 | C | 2 |
| 2015 | A | 4 |
| 2015 | D | 3 |
按a分组按b字段排序,对c取前后各一行的和
1 | select |
| year | dept | sum_range_score |
|---|---|---|
| 2014 | A | 1 |
| 2014 | B | 5 |
| 2014 | C | 1 |
| 2015 | A | 3 |
| 2015 | D | 4 |
按a分组按b字段排序,对c取平均值
前一行与当前行的均值
1 | select |
| year | dept | score | lag_score |
|---|---|---|---|
| 2014 | A | 3 | |
| 2014 | B | 1 | 3 |
| 2014 | C | 2 | 1 |
| 2015 | A | 4 | |
| 2015 | D | 3 | 4 |
1 | select |
| year | dept | score | avg_lag2 |
|---|---|---|---|
| 2014 | A | 3 | 3 |
| 2014 | B | 1 | 2.0000 |
| 2014 | C | 2 | 1.5000 |
| 2015 | A | 4 | 4 |
| 2015 | D | 3 | 3.5000 |