MySql 行转列的玩法 ,实战案例教学(MAX函数的坑简析)

前言

既然有人问到mysql的行专列,那么就一块来玩一玩。

MySql 行转列的玩法 ,实战案例教学(MAX函数的坑简析)_第1张图片

 

正文

先准备个样例数据:
 

 环境气候表 (假装是一张用于接收某个检测数据每天上报过来的环境数据)

建表SQL:
 

CREATE TABLE `env_climate` (
    `id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
    `area` VARCHAR(50) NULL DEFAULT NULL COMMENT '地区' COLLATE 'utf8_general_ci',
    `item_name` VARCHAR(50) NULL DEFAULT NULL COMMENT '参数项名' COLLATE 'utf8_general_ci',
    `item_value` VARCHAR(50) NULL DEFAULT NULL COMMENT '参数项值' COLLATE 'utf8_general_ci',
    `date` VARCHAR(50) NULL DEFAULT NULL COMMENT '日期' COLLATE 'utf8_general_ci',
    PRIMARY KEY (`id`) USING BTREE
)
COMMENT='环境气候表'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1
;

然后填充一些数据:

INSERT INTO `env_climate` (`id`, `area`, `item_name`, `item_value`, `date`) VALUES (1, '深圳', '温度', '12', '2022-11-01');
INSERT INTO `env_climate` (`id`, `area`, `item_name`, `item_value`, `date`) VALUES (2, '深圳', '湿度', NULL, '2022-11-01');
INSERT INTO `env_climate` (`id`, `area`, `item_name`, `item_value`, `date`) VALUES (3, '深圳', '光照', '1300', '2022-11-01');
INSERT INTO `env_climate` (`id`, `area`, `item_name`, `item_value`, `date`) VALUES (4, '成都', '温度', '45', '2022-11-01');
INSERT INTO `env_climate` (`id`, `area`, `item_name`, `item_value`, `date`) VALUES (5, '成都', '湿度', '32', '2022-11-01');
INSERT INTO `env_climate` (`id`, `area`, `item_name`, `item_value`, `date`) VALUES (6, '成都', '光照', '1300', '2022-11-01');
INSERT INTO `env_climate` (`id`, `area`, `item_name`, `item_value`, `date`) VALUES (7, '成都', '湿度', '32', '2022-11-02');
INSERT INTO `env_climate` (`id`, `area`, `item_name`, `item_value`, `date`) VALUES (8, '成都', '温度', '26', '2022-11-02');
INSERT INTO `env_climate` (`id`, `area`, `item_name`, `item_value`, `date`) VALUES (9, '成都', '光照', '230', '2022-11-02');
INSERT INTO `env_climate` (`id`, `area`, `item_name`, `item_value`, `date`) VALUES (10, '深圳', '温度', '26', '2022-11-02');
INSERT INTO `env_climate` (`id`, `area`, `item_name`, `item_value`, `date`) VALUES (11, '深圳', '湿度', '34', '2022-11-02');
INSERT INTO `env_climate` (`id`, `area`, `item_name`, `item_value`, `date`) VALUES (12, '深圳', '光照', '5000', '2022-11-02');

看一下示例数据情况:
 

MySql 行转列的玩法 ,实战案例教学(MAX函数的坑简析)_第2张图片

 MySql 行转列的玩法 ,实战案例教学(MAX函数的坑简析)_第3张图片

 

行转列的结果:

MySql 行转列的玩法 ,实战案例教学(MAX函数的坑简析)_第4张图片

可以看到,本来温度、地区 、数值 都是一行行的数据 ,我们转列之后,以日期&地区的维度,直观看到了 属于这个地区的 温度、湿度、光照 等数据。

怎么玩的呢?

接下来看SQL,介绍 3种小玩法。

第一种  用MAX + GROUP  实现  (有坑,文末会讲)

SELECT DATE AS '日期', AREA, 
MAX(CASE WHEN item_name='温度' THEN item_value ELSE '--'END) AS "温度",
MAX(CASE WHEN item_name='湿度' THEN item_value ELSE '--'END) AS "湿度", 
MAX(CASE WHEN item_name='光照' THEN item_value ELSE '--'END) AS "光照"
FROM env_climate
GROUP BY AREA, DATE 

效果:

 MySql 行转列的玩法 ,实战案例教学(MAX函数的坑简析)_第5张图片

 

第二种 使用SUM +GROUP BY  实现

SELECT DATE AS '日期', AREA AS '地区', 
SUM(CASE WHEN item_name='温度' THEN item_value ELSE '--'END) AS "温度",
SUM(CASE WHEN item_name='湿度' THEN item_value ELSE '--'END) AS "湿度", 
SUM(CASE WHEN item_name='光照' THEN item_value ELSE '--'END) AS "光照"
FROM env_climate
GROUP BY AREA, DATE 

效果:

ps:因为SUM是累计,所以只针对数字做了计算,可以看到我们value值尽管是字符串类型,mysql在做计算还是很友好过滤掉了非数字的值,所以计算完后返回的值,变成蓝色,代表是数字
MySql 行转列的玩法 ,实战案例教学(MAX函数的坑简析)_第6张图片

 

第三种 使用 GROUP_CONCAT +GROUP BY  实现

SELECT DATE AS '日期', AREA, 
    group_concat(CASE WHEN item_name = '温度' THEN item_value END SEPARATOR '') '温度',
    group_concat(CASE WHEN item_name = '湿度' THEN item_value END SEPARATOR '') '湿度',
    group_concat(CASE WHEN item_name = '光照' THEN item_value END SEPARATOR '') '光照'
FROM env_climate
GROUP BY DATE,AREA;

效果:
 

MySql 行转列的玩法 ,实战案例教学(MAX函数的坑简析)_第7张图片

 

!!!!!注意点 

MySql 行转列的玩法 ,实战案例教学(MAX函数的坑简析)_第8张图片

我们把NULL 情况 赋值 ‘ 无’  Max 的劣质行为就暴露了:

MAX(CASE WHEN item_name='湿度' THEN item_value ELSE '无'END) AS "湿度"

MySql 行转列的玩法 ,实战案例教学(MAX函数的坑简析)_第9张图片

 

 

为什么会这样呢?

 其实如果有经验的SQL人,都知道MAX 的玩法是有坑的,它只保证了 被MAX 的这个值的最大值。

然后如果你是字符串去MAX, 那么 mysql就会去比较这个值的 从左到右的一个个字符去做比较。 

这么说可能还是有人不清楚。

 立马做几个小例子,来讲这些坑暴露出来给大知道。

坑一 针对 varchar 做 max 、order排序

搞个新表,age字段故意搞成 字符串 varchar 类型 

MySql 行转列的玩法 ,实战案例教学(MAX函数的坑简析)_第10张图片

MySql 行转列的玩法 ,实战案例教学(MAX函数的坑简析)_第11张图片

好玩的来咯:
 

可以看到针对varchar 类型 ,去做 max ,显然是跟我们想象不一样的。

MySql 行转列的玩法 ,实战案例教学(MAX函数的坑简析)_第12张图片

 稀缺手绘真迹解释:MySql 行转列的玩法 ,实战案例教学(MAX函数的坑简析)_第13张图片

 MySql 行转列的玩法 ,实战案例教学(MAX函数的坑简析)_第14张图片

其实这仅仅是一个针对varchar 使用max的 一个坑。 

那么其实使用max 和 group by ,还有坑没?  有。

坑二 ,max和group 多字段 乱数据

表数据:
MySql 行转列的玩法 ,实战案例教学(MAX函数的坑简析)_第15张图片

 我们  想根据SID 分组 找出 score最大的 行值 ,然后展示当前行的 sid 、score、 cid :

错误踩坑:
 


SELECT sid,cid,MAX(score) as score
FROM stu_score
GROUP BY sid;

 MySql 行转列的玩法 ,实战案例教学(MAX函数的坑简析)_第16张图片

 

 MySql 行转列的玩法 ,实战案例教学(MAX函数的坑简析)_第17张图片

 

因为用max 配和 group的时候, mysql是个脑子转的很快但是想东西很简单的小孩,他只管把max的这个字段超出最大值,然后其他字段都是 图快,先拿到符合条件 sid = 1001的那行,就把相关其他字段都直接赋值了。 所以 第一个sid=1001 的 那行,cid是101, 赋值。

所以出来了

MySql 行转列的玩法 ,实战案例教学(MAX函数的坑简析)_第18张图片

 

不好意思,这篇是讲行转列,不小心跑题了。 那就先到这里吧。

 

你可能感兴趣的:(MySQL,mysql,数据库,行转列,max,坑)