求助:MySQL动态实现行列转换生成指定报表的查询方案
MySQL 行列转换解决方案
静态场景(已知所有Blok名称)
如果你的Blok数量固定(比如示例中的Blok 1、Blok 2),可以直接用以下静态查询实现需求:
SELECT 'Tahun Tanam' AS Blok, MAX(CASE WHEN `Nama Blok` = 'Blok 1' THEN Tahun_tanam END) AS `Blok 1`, MAX(CASE WHEN `Nama Blok` = 'Blok 2' THEN Tahun_tanam END) AS `Blok 2` UNION ALL SELECT 'Luas' AS Blok, MAX(CASE WHEN `Nama Blok` = 'Blok 1' THEN Luas END) AS `Blok 1`, MAX(CASE WHEN `Nama Blok` = 'Blok 2' THEN Luas END) AS `Blok 2` UNION ALL SELECT 'Jumlah Pokok' AS Blok, MAX(CASE WHEN `Nama Blok` = 'Blok 1' THEN Jumlah_pokok END) AS `Blok 1`, MAX(CASE WHEN `Nama Blok` = 'Blok 2' THEN Jumlah_pokok END) AS `Blok 2`;
逻辑说明
- 用
UNION ALL将三个属性维度(种植年份、面积、树木数量)合并成结果表的行 - 每个子查询中通过
CASE语句匹配对应Blok,用MAX聚合确保只返回对应Blok的有效值(每个Blok在对应属性下仅一条数据,MAX不影响结果)
动态场景(Blok名称不固定/可新增)
如果后续会新增Blok,静态查询需要手动修改,此时可以用动态SQL自动生成列:
SET @sql = NULL; SELECT GROUP_CONCAT(DISTINCT CONCAT( 'MAX(CASE WHEN `Nama Blok` = ''', `Nama Blok`, ''' THEN ', column_name, ' END) AS `', `Nama Blok`, '`' ) ) INTO @sql FROM information_schema.columns WHERE table_name = '你的表名' -- 替换成实际数据表名 AND column_name IN ('Tahun_tanam', 'Luas', 'Jumlah_pokok'); SET @sql = CONCAT(' SELECT ''Tahun Tanam'' AS Blok, ', REPLACE(@sql, 'Tahun_tanam', 'Tahun_tanam'), ' UNION ALL SELECT ''Luas'' AS Blok, ', REPLACE(@sql, 'Tahun_tanam', 'Luas'), ' UNION ALL SELECT ''Jumlah Pokok'' AS Blok, ', REPLACE(@sql, 'Tahun_tanam', 'Jumlah_pokok'), ' '); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
逻辑说明
- 从
information_schema.columns中获取目标表的指定列,拼接出每个Blok对应的CASE语句片段 - 通过字符串替换生成三个属性维度的查询语句,再用UNION ALL合并
- 最后预编译并执行动态生成的SQL语句
注意:使用动态SQL时需要确保用户有information_schema的访问权限,同时替换语句中的你的表名为实际数据表名称。
内容的提问来源于stack exchange,提问作者Muhammad Akbar
相关产品推荐
相关产品推荐

