网站首页 > 知识剖析 正文
写在前面
在工作中, 有时候需要开发报表。 有时候报表需要将时间做为表头。 这个就需要用到行列转置。 本文以 mysql 为例。 看看,它的行列转置应该如何做。
测试步骤
建表语句
CREATE TABLE test_stats (
id INT AUTO_INCREMENT PRIMARY KEY,
location VARCHAR(255),
test_name VARCHAR(255),
test_type VARCHAR(255),
dev_id varchar(255),
countDay DATE,
test_value DOUBLE,
test_count DOUBLE
);
插入数据
INSERT INTO test_stats (location, test_name, test_type,dev_id, countDay, test_value, test_count)
VALUES
('河南', '鹤壁', '测试值', '1','2024-07-01', 5, 1),
('河南', '鹤壁', '测试值', '2','2024-07-02', 6, 2),
('河南', '鹤壁', '次数', '1','2024-07-01', 2.0, 3),
('河南', '鹤壁', '次数', '2','2024-07-02', 3.0, 4);
查询结果
select * from test_stats;
行列转置
SET SESSION group_concat_max_len = 10000000;
SET @sql_value = NULL;
SET @sql_count = NULL;
SELECT
COALESCE(
GROUP_CONCAT(DISTINCT
CONCAT(
'SUM(CASE WHEN countDay = ''',
countDay,
''' THEN test_value ELSE 0 END) AS `',
DATE_FORMAT(countDay, '%Y-%m-%d'),
'`'
)
),
'0 AS `no_data`'
) INTO @sql_value
FROM test_stats
WHERE countDay BETWEEN '2024-07-01' AND '2024-07-02';
SELECT
COALESCE(
GROUP_CONCAT(DISTINCT
CONCAT(
'SUM(CASE WHEN countDay = ''',
countDay,
''' THEN test_count ELSE 0 END) AS `',
DATE_FORMAT(countDay, '%Y-%m-%d'),
'`'
)
),
'0 AS `no_data`'
) INTO @sql_count
FROM test_stats
WHERE countDay BETWEEN '2024-07-01' AND '2024-07-02';
-- 构建故障时长的最终SQL
SET @sql_value = CONCAT('SELECT dev_id, ''test_value'' AS metric_type, ', @sql_value, ',
SUM(test_value) AS `合计`
FROM test_stats
WHERE countDay BETWEEN ''2024-07-01'' AND ''2024-07-02''
GROUP BY dev_id');
SET @sql_count = CONCAT('SELECT dev_id, ''test_count'' AS metric_type, ', @sql_count, ',
SUM(test_count) AS `合计`
FROM test_stats
WHERE countDay BETWEEN ''2024-07-01'' AND ''2024-07-02''
GROUP BY dev_id');
-- 使用UNION ALL合并两个查询
SET @sql = CONCAT('(', @sql_value, ') UNION ALL (', @sql_count, ') ORDER BY dev_id, metric_type');
-- 准备并执行最终的动态SQL
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
执行结果
写在最后
最终,上边的 sql 执行,以 dev_id 进行分组, 将相关指标进行统计, 以日期作为表头,并且增加了一个合计功能。 上边的 dev_id 也可以换成 dev_name 等, 看起来效果会更直观。
上边的这段行列转置的sql, 看起来像一个存储过程, 不过, 它是可以直接放到 mybatis 中的 <select>标签中的。 sql中传入的 时间值(比如: 2024-07-01),可以作为 mybatis 中 传入条件。 mybatis 的 接口可以直接返回一个 map 即可。 这样就可以获取到相关的统计数据了。
不过,做报表一般都是专门的一些报表工具, 比如: 润乾报表等。 对于简单的需求, 能直接用 mysql 的 sql语句搞定的, 也是一种简单的方法。
- 上一篇: 206.C# XML读取XPath
- 下一篇: MySQL 日期函数
猜你喜欢
- 2025-08-03 mysql 工作时工作日函数 计算两个时间间隔分钟数
- 2025-08-03 开源鸿蒙OpenHarmony 5.1.0(API 18)正式上线:进一步增强ArkUI
- 2025-08-03 MySql
- 2025-08-03 MYSQL自动导出某表数据到EXCEL的方案
- 2025-08-03 MySQL进行整库数据备份「表(结构+数据)、视图、函数、事件」
- 2025-08-03 SQL高效使用20招:数据分析师必备技巧
- 2025-08-03 MySQL 中时间函数详解,及加减计算总结和使用!
- 2025-08-03 MySQL 日期函数
- 最近发表
- 标签列表
-
- xml (46)
- css animation (57)
- array_slice (60)
- htmlspecialchars (54)
- position: absolute (54)
- datediff函数 (47)
- array_pop (49)
- jsmap (52)
- toggleclass (43)
- console.time (63)
- .sql (41)
- ahref (40)
- js json.parse (59)
- html复选框 (60)
- css 透明 (44)
- css 颜色 (47)
- php replace (41)
- css nth-child (48)
- min-height (40)
- xml schema (44)
- css 最后一个元素 (46)
- location.origin (44)
- table border (49)
- html tr (40)
- video controls (49)