sql 行转列 日周月 图表统计

目录

目录

需求

准备

分析

按月分组

行转列

错误版本

正确版本

分析

行转列

分析

按周分组

行转列

本年


需求

页面有三个按钮  日周月,统计一周中每天(日),一月中每周(周),一年中每月(月),设备台数

点击 按钮月,出现类似下图这种

sql 行转列 日周月 图表统计_第1张图片

返回给前端,如果某个月份没有数据,x轴该月份不是没有了嘛,当然可以有其他方式来解决,本文主要讲下行转列

准备

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for robot
-- ----------------------------
DROP TABLE IF EXISTS `robot`;
CREATE TABLE `robot`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `createtime` datetime NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of robot
-- ----------------------------
INSERT INTO `robot` VALUES (1, '1号机器人', '2024-02-02 23:07:37');
INSERT INTO `robot` VALUES (2, '2号机器人', '2024-01-01 23:07:37');
INSERT INTO `robot` VALUES (3, '3号机器人', '2024-02-02 23:07:37');
INSERT INTO `robot` VALUES (4, '4号机器人', '2024-01-01 15:41:42');
INSERT INTO `robot` VALUES (5, '5号机器人', '2024-03-03 15:51:25');
INSERT INTO `robot` VALUES (6, '6号机器人', '2024-01-26 11:34:46');

SET FOREIGN_KEY_CHECKS = 1;

sql 行转列 日周月 图表统计_第2张图片

注:此处举例都是同一年,其他年份where过滤一下即可,过滤方式于文章末尾

分析

需要按照月去统计,那么将相同月合为一组,统计ID为数量即可,那月怎么划分?

从第6位开始后两位即为月,SUBSTRING(createtime, 6, 2)

sql 行转列 日周月 图表统计_第3张图片

按月分组

SELECT SUBSTRING(createtime, 6, 2) dayOfMonth, count(ID) num
FROM `robot`
GROUP BY SUBSTRING(createtime, 6, 2)

sql 行转列 日周月 图表统计_第4张图片

行转列

错误版本

select
case when dayOfMonth = 1 then num else 0 end January,
case when dayOfMonth = 2 then num else 0 end February,
case when dayOfMonth = 3 then num else 0 end March,
case when dayOfMonth = 4 then num else 0 end April,
case when dayOfMonth = 5 then num else 0 end May,
case when dayOfMonth = 6 then num else 0 end June,
case when dayOfMonth = 7 then num else 0 end July,
case when dayOfMonth = 8 then num else 0 end August,
case when dayOfMonth = 9 then num else 0 end September,
case when dayOfMonth = 10 then num else 0 end October,
case when dayOfMonth = 11 then num else 0 end November,
case when dayOfMonth = 12 then num else 0 end December
from (
	SELECT SUBSTRING(createtime, 6, 2) dayOfMonth, count(ID) num
	FROM `robot`
	GROUP BY SUBSTRING(createtime, 6, 2)
) t

sql 行转列 日周月 图表统计_第5张图片

????????????   

咋就成这样了,难不成每次 case when 同一个字段 end 不同字段 时他会将之前的结果表每行都扫描一次?那我取有值的一次是不是就解决了?怎么取?有值的那次是最大的

正确版本

select
MAX(case when dayOfMonth = 1 then num else 0 end) January,
MAX(case when dayOfMonth = 2 then num else 0 end) February,
MAX(case when dayOfMonth = 3 then num else 0 end) March,
MAX(case when dayOfMonth = 4 then num else 0 end) April,
MAX(case when dayOfMonth = 5 then num else 0 end) May,
MAX(case when dayOfMonth = 6 then num else 0 end) June,
MAX(case when dayOfMonth = 7 then num else 0 end) July,
MAX(case when dayOfMonth = 8 then num else 0 end) August,
MAX(case when dayOfMonth = 9 then num else 0 end) September,
MAX(case when dayOfMonth = 10 then num else 0 end) October,
MAX(case when dayOfMonth = 11 then num else 0 end) November,
MAX(case when dayOfMonth = 12 then num else 0 end) December
from (
	SELECT SUBSTRING(createtime, 6, 2) dayOfMonth, count(ID) num
	FROM `robot`
	GROUP BY SUBSTRING(createtime, 6, 2)
) t

sql 行转列 日周月 图表统计_第6张图片

sql 行转列 日周月 图表统计_第7张图片

分析

需要一个函数帮我确定给定的日期是星期几,然后再分组统计

SELECT DAYNAME(createtime) dayOfWeek, count(ID) num	
FROM `robot` 
GROUP BY DAYNAME(createtime) 

sql 行转列 日周月 图表统计_第8张图片

行转列

select
MAX(case when dayOfWeek = 'Monday' then num else 0 end) Monday,
MAX(case when dayOfWeek = 'Tuesday' then num else 0 end) Tuesday,
MAX(case when dayOfWeek = 'Wednesday' then num else 0 end) Wednesday,
MAX(case when dayOfWeek = 'Thursday' then num else 0 end) Thursday,
MAX(case when dayOfWeek = 'Friday' then num else 0 end) Friday,
MAX(case when dayOfWeek = 'Saturday' then num else 0 end) Saturday,
MAX(case when dayOfWeek = 'Sunday' then num else 0 end) Sunday
from (
	SELECT DAYNAME(createtime) dayOfWeek, count(ID) num	
	FROM `robot` 
	GROUP BY DAYNAME(createtime) 
) t

sql 行转列 日周月 图表统计_第9张图片

公司要求的是:

1-7号固定为第一周,8-14号固定为第二周,15-21固定为第三周,剩下的为第四周

注:如果不是这种规则,网上找找周相关函数,很容易找到的

分析

需要按照他们定的规则划分周,那我怎么知道日期几号?

SUBSTRING(createtime, 9, 2)    9号位置开始后两位为天

sql 行转列 日周月 图表统计_第10张图片

按周分组

	SELECT CASE WHEN SUBSTRING(createtime, 9, 2) <= 7 THEN 'firstWeek'
       WHEN SUBSTRING(createtime, 9, 2) <= 14 THEN 'secondWeek'
       WHEN SUBSTRING(createtime, 9, 2) <= 21 THEN 'thirdWeek'
       ELSE 'fourWeek' END as `week`, count(ID) num
	FROM `robot` 
	GROUP BY 
	CASE WHEN SUBSTRING(createtime, 9, 2) <= 7 THEN 'firstWeek'
       WHEN SUBSTRING(createtime, 9, 2) <= 14 THEN 'secondWeek'
       WHEN SUBSTRING(createtime, 9, 2) <= 21 THEN 'thirdWeek'
       ELSE 'fourWeek' END

sql 行转列 日周月 图表统计_第11张图片

行转列

select
MAX(case when `week` = 'firstWeek' then num else 0 end) firstWeek,
MAX(case when `week` = 'secondWeek' then num else 0 end) secondWeek,
MAX(case when `week` = 'thirdWeek' then num else 0 end) thirdWeek,
MAX(case when `week` = 'fourWeek' then num else 0 end) fourWeek
from (
	SELECT CASE WHEN SUBSTRING(createtime, 9, 2) <= 7 THEN 'firstWeek'
       WHEN SUBSTRING(createtime, 9, 2) <= 14 THEN 'secondWeek'
       WHEN SUBSTRING(createtime, 9, 2) <= 21 THEN 'thirdWeek'
       ELSE 'fourWeek' END as `week`, count(ID) num
	FROM `robot` 
	GROUP BY 
	CASE WHEN SUBSTRING(createtime, 9, 2) <= 7 THEN 'firstWeek'
       WHEN SUBSTRING(createtime, 9, 2) <= 14 THEN 'secondWeek'
       WHEN SUBSTRING(createtime, 9, 2) <= 21 THEN 'thirdWeek'
       ELSE 'fourWeek' END
) t

sql 行转列 日周月 图表统计_第12张图片

本年

将上面的sql用下面 where 后面的过滤一下即可

SELECT *
FROM robot
WHERE YEAR(createtime) = YEAR(CURDATE());	

sql 行转列 日周月 图表统计_第13张图片

sql 行转列 日周月 图表统计_第14张图片

你可能感兴趣的:(java,数据库)