本文主要介绍在MySQL中改变行和列的方法,帮助你更好的理解和学习MySQL的使用。感兴趣的朋友可以了解一下。
MySQL行转列操作
所谓行到列操作,就是把一个表格的行信息转换成列信息,可能比较笼统。这里有一个例子,如下:
- - - -
| ID |用户名|课程|分数|
- - - -
|||张三|数学||
|||张三|中文||
|||张三|英语||
|||李四|数学||
|||李四|中文||
|||李四|英语||
|||王武||数学|数学
|||王武|中文||
|||王武|英语||
- - - -
集合中的行(0.00秒)
- - - -
|用户名|数学|中文|英文|
- - - -
|张三|||
|李四||||
||||||王武
- - - -
集合中的行(0.00秒)
在上面的例子中,表1给出了三个学生的三个成绩,而表2将表1中的行记录信息(学科,姓名)转换为列信息,并根据不同的user_name分组显示。
1 case when操作方法
要实现以上功能,我们需要分析。首先我们需要生成三列,分别是数学、语文、英语,然后为每一列中的值填入相应的数据。这里我们需要使用mysql的case when then end操作,也就是条件操作。关于这个条件语句,首先我们给出一个解释:
案例栏
当条件1然后结果1
当条件2然后结果2
当条件3然后结果3
否则结果4
结束
上面的语法可以理解为当列的值满足条件1时用result1替换列的值,以此类推,当列的值不满足时用result4替换列的值。
现在开始实验:
首先,我们创建一个表并插入以下数据:
MySQL-yeyz:select * from test _ TBL;
- - - -
| ID |用户名|课程|分数|
- - - -
|||张三|数学||
|||张三|中文||
|||张三|英语||
|||李四|数学||
|||李四|中文||
|||李四|英语||
|||王武||数学|数学
|||王武|中文||
|||王武|英语||
- - - -
集合中的行(0.00秒)
语法的时候按照上面的案例,当课程是‘数学’的时候,我们定义一列‘数学’,填写它的分数。如果我们遇到中文或英文,那么用0替换它,我们一般可以写出下面的SQL:
mysql-yeyz :SELECT用户名,
(案例课程当‘数学’结束后再评分)数学
FROM test _ tbl
- -
|用户名|数学|
- -
|张三||
|张三||
|张三||
|李四||
|李四||
|李四||
||王武||
||王武||
||王武||
- -
集合中的行(0.00秒)
我们发现上表只有两列。根据SQL规则,我们还可以将 Chinese 和 English 的值相加,一次多写几列,如下所示:
mysql-yeyz :SELECT用户名,
--(案例课程当‘数学’然后得分否则结束)数学,
-(案例课程当‘语言’然后得分否则结束)语言,
-(当“英语”时,案例课程得分,否则结束)英语
-FROM test _ TBL;
- - - -
|用户名|数学|中文|英文|
- - - -
|张三|||
|张三|||
|张三|||
|李四||||
|李四||||
|李四||||
||||||王武
||||||王武
||||||王武
- - - -
集合中的行(0.00秒)
太好了,现在我们有了所有的记录,我们几乎达到了我们的目标。看与最终结果的差距:
- - - -
|用户名|数学|中文|英文|
- - - -
|张三|||
|李四||||
||||||王武
- - - -
好像剩下的就是把同名同学的信息组合起来了。我们很自然的想到group_by(user_name)的运算,需要配合一些聚合函数(MAX、MIN、AVG、SUM、COUNT等。).由于每条记录只包含当前学科的分数,其他学科的分数都是0,所以使用MAX函数和SUM函数的结果是一样的,但是我们不能使用AVG函数和MIN函数,这个应该很好理解。
这里我们给出最终结果:
MySQL-yeyz 13:55:52选择用户名,
-MAX(案例课程当‘数学’然后评分ELSE END)数学,
-MAX(CASE course WHEN language THEN score ELSE END)语言,
-MAX(当“英语”时为案例课程,然后得分,否则结束)英语
-来自测试_tbl
-按用户名分组;
- - - -
|用户名|数学|中文|英文|
- - - -
|张三| 34 | 58 | 58
|李四| 45 | 87 | 45
王|吴| 76 | 34 | 89
- - - -
集合中的3行(0.00秒)
mysql-yeyz :SELECT用户名,
-sum(案例课程当‘数学’然后得分否则结束)数学,
-sum(案例课程当‘语言’然后得分否则结束)语言,
-sum(当“英语”时为案例课程,然后得分,否则结束)英语
-来自测试_tbl
-按用户名分组;
- - - -
|用户名|数学|中文|英文|
- - - -
|张三| 34 | 58 | 58
|李四| 45 | 87 | 45
王|吴| 76 | 34 | 89
- - - -
集合中的3行(0.00秒)
mysql-yeyz :SELECT用户名,
-MIN(案例课程当‘数学’然后评分ELSE END)数学,
-MIN(CASE course WHEN language THEN score ELSE END)语言,
-MIN(当“英语”时为案例课程,然后得分,否则结束)英语
-来自测试_tbl
-按用户名分组;
- - - -
|用户名|数学|中文|英文|
- - - -
|张三| 0 | 0
|李四| 0 | 0
|王武| 0 | 0
- - - -
集合中的3行(0.00秒)
可以看出,使用MAX和SUM的结果是一样的,但是使用MIN作为聚合函数会导致最终输出结果为0,因为每次都选择user_name指定的学科的最小值,即0。这个结果很好理解。
2 if操作方法
以上case when的操作方法是明白的,所以if的操作方法也是容易理解的。原理是相同的,但是case when的语法被转换为if模式,如下所示
MySQL-yeyz 14:12:42选择用户名,
-MAX(if (course= mathematics ,score,)数学,
-MAX(if (course= language ,score,)语言,
-MAX(if (course= English ,score,)英语
-来自测试_tbl
-按用户名分组;
- - - -
|用户名|数学|中文|英文|
- - - -
|张三| 34 | 58 | 58
|李四| 45 | 87 | 45
王|吴| 76 | 34 | 89
- - - -
集合中的3行(0.00秒)
3 添加total列
在我们实现了基本的行到列的转换之后,我们现在需要向转换后的表中添加一个总计字段。我们可以通过以下方法添加该字段,即在开始统计时,我们也可以统计分值,如下所示:
MySQL-yeyz 14:18:06选择用户名,
--(案例课程当‘数学’然后得分否则结束)数学,
-(案例课程当‘语言’然后得分否则结束)语言,
-(案例课程当‘英语’然后得分否则结束)英语,
-(得分)总计
-FROM test _ TBL;
- - - - -
|用户名|数学|中文|英文|总计|
- - - - -
|张三| 34 | 0 | 0 | 34
|张三| 0 | 58 | 0 | 58
|张三| 0 | 0 | 58 | 58
|李四| 45 | 0 | 0 | 45 | 45
|李四| 0 | 87 | 0 | 87
|李四| 0 | 0 | 45 | 45 |
王|吴| 76 | 0 | 0 | 76
王武| 0 | 34 | 0 | 34
|王武| 0 | 0 | 89 | 89
- - - - -
集合中的9行(0.00秒)
以上结果是没有聚合的结果。这里需要注意的是,如果要合计,前三列可以使用sum或max的方法,最后一列必须使用sum的方法,因为我们要求的是总分,使用max的方法会得出得分最高的值。最终的sql如下所示:
MySQL-yeyz 14:18:29选择用户名,
-sum(案例课程当‘数学’然后得分否则结束)数学,
-sum(案例课程当‘语言’然后得分否则结束)语言,
-sum(案例课程当‘英语’然后得分否则结束)英语,
-总计(得分)
-来自测试_tbl
-按用户名分组;
- - - - -
|用户名|数学|中文|英文|总计|
- - - - -
|张三| 34 | 58 | 58 | 150
|李四| 45 | 87 | 45 | 177 |
|王武76 | 34 | 89 | 199 |人
- - - - -
集合中的3行(0.00秒)
4 简单方法 group_concat
如果我们对结果的显示格式不是那么细致,也可以用一个粗略的方法,就是group_concat函数,把所有的列写在一起,用一个字段表示。效果如下:
MySQL-yeyz 14:19:13选择用户名,
Group _ concat (`course `,:,score)作为结果
来自测试_tbl
按用户名分组;
- -
|用户名|成就|
- -
|张三|数学:34,语文:58,英语:58 |
|李四|数学:45,语文:87,英语:45 |
|王武|数学:76,语文:34,英语:89 |
- -
集合中的3行(0.00秒)
这种方法相当于直接对原表进行分组,也可以应对一定的应用场景。
以上是MySQL中行转换方法的详细内容。关于MySQL中行转换的更多信息,请关注我们的其他相关文章!