统一SQL-支持unpivot列转行

统一SQL介绍

https://www.light-pg.com/docs/LTSQL/current/index.html

源和目标

源数据库:Oracle

目标数据库:TDSQL-MySQL

操作目标

在Oracle中,可以使用unpivot将列转换成行,在TDSQL-MySQL中没有对应的功能,由此,通过统一SQL进行语句改写,在限定条件下支持unpivot的功能。

统一SQL转换

Oracle 的unpivot语法图

统一SQL支持语法图

上图矩形框部分

转换方案

使用TDSQL-MySQL的 UNION ALL 特性进行Oracle unpivot的替换

转换案例

复制代码
-- 前置准备Oracle-SQL:
CREATE TABLE unisql_unpivot(id INT,name VARCHAR(64),chinese NUMBER,math INT,english INT);
INSERT INTO unisql_unpivot VALUES(1,'张三',70,90,95);
INSERT INTO unisql_unpivot VALUES(2,'李四',75,85,90);
INSERT INTO unisql_unpivot VALUES(3,'张三',90,90,90);
drop table unisql_unpivot;


-- 转换前Oracle SQL:
SELECT id,name,score,subject FROM unisql_unpivot UNPIVOT(score FOR subject IN(chinese, math, english)) WHERE id IN (1, 2, 3) ORDER BY id;
ID|NAME|SCORE|SUBJECT|
--+----+-----+-------+
1|张三  |   70|CHINESE|
1|张三  |   90|MATH   |
1|张三  |   95|ENGLISH|
2|李四  |   75|CHINESE|
2|李四  |   85|MATH   |
2|李四  |   90|ENGLISH|
3|张三  |   90|CHINESE|
3|张三  |   90|MATH   |
3|张三  |   90|ENGLISH|

-- 转换后TDSQL-MySQL
SELECT `id`,`name`,`chinese` AS `score`,'CHINESE' AS `subject` FROM `unisql_unpivot` WHERE `id` IN (1,2,3) UNION ALL SELECT `id`,`name`,`math` AS `score`,'MATH' AS `subject` FROM `unisql_unpivot` WHERE `id` IN (1,2,3) UNION ALL SELECT `id`,`name`,`english` AS `score`,'ENGLISH' AS `subject` FROM `unisql_unpivot` WHERE `id` IN (1,2,3) ORDER BY `id`
id|name|score|subject|
--+----+-----+-------+
1|张三  |   70|CHINESE|
1|张三  |   95|ENGLISH|
1|张三  |   90|MATH   |
2|李四  |   85|MATH   |
2|李四  |   75|CHINESE|
2|李四  |   90|ENGLISH|
3|张三  |   90|MATH   |
3|张三  |   90|CHINESE|
3|张三  |   90|ENGLISH|


 -- 转换前Oracle SQL:
SELECT id,name,score,subject FROM unisql_unpivot UNPIVOT(score FOR subject IN(chinese, math, english)) WHERE id IN (1, 2, 3) ORDER BY id,name,score,subject OFFSET 1 ROWS FETCH NEXT 2 ROWS ONLY;
ID|NAME|SCORE|SUBJECT|
--+----+-----+-------+
1|张三  |   90|MATH   |
1|张三  |   95|ENGLISH|

-- 转换后TDSQL-MySQL
    SELECT `id`,`name`,`chinese` AS `score`,'CHINESE' AS `subject` FROM `unisql_unpivot` WHERE `id` IN (1,2,3) UNION ALL SELECT `id`,`name`,`math` AS `score`,'MATH' AS `subject` FROM `unisql_unpivot` WHERE `id` IN (1,2,3) UNION ALL SELECT `id`,`name`,`english` AS `score`,'ENGLISH' AS `subject` FROM `unisql_unpivot` WHERE `id` IN (1,2,3) ORDER BY `id`,`name`,`score`,`subject` LIMIT 1,2
id|name|score|subject|
--+----+-----+-------+
1|张三  |   90|MATH   |
1|张三  |   95|ENGLISH|

使用限制

复制代码
统一SQL当前对unpivot转换使用限制如下:
1. 只支持在单表查询语句中使用,参考如下:
  SELECT id,name,score AS sc,subject AS su FROM unisql_unpivot UNPIVOT(score FOR subject IN(chinese, math, english)) WHERE id IN (1, 2, 3,4,5) ORDER BY id;
2. 只支持单字段的unpivot,如上(score for subject)
3. 统一SQL会将unpivot in中的字段转换为大写,如上(chinese-->CHINESE, math-->MATH, english-->ENGLISH)
4. 不支持join,with, 子查询,group by, having,rownum
5. 不支持unpivot和unpivot for字段上使用函数,表达式
6. 不支持unpivot in语句中的字段使用AS
7. 分页查询存在offset时必须有fetch
8. 注意oracle和tdmysql字符集,排序规则等底层实现存在差异,排序字段需要保证是唯一序,否则可能导致两个库执行结果获取结果顺序不一致。
相关推荐
麦兜*14 分钟前
MongoDB 6.0 新特性解读:时间序列集合与加密查询
数据库·spring boot·mongodb·spring·spring cloud·系统架构
chat2tomorrow17 分钟前
数据采集平台的起源与演进:从ETL到数据复制
大数据·数据库·数据仓库·mysql·低代码·postgresql·etl
稻草人想看远方20 分钟前
关系型数据库和非关系型数据库
数据库
考虑考虑21 分钟前
Postgerssql格式化时间
数据库·后端·postgresql
依稀i12324 分钟前
Spring Boot + MySQL 创建超级管理员
spring boot·mysql
千里码aicood29 分钟前
【springboot+vue】党员党建活动管理平台(源码+文档+调试+基础修改+答疑)
java·数据库·spring boot
Chan1633 分钟前
【智能协同云图库】基于统一接口架构构建多维度分析功能、结合 ECharts 可视化与权限校验实现用户 / 管理员图库统计、通过 SQL 优化与流式处理提升数据
java·spring boot·后端·sql·spring·intellij-idea·echarts
TDengine (老段)1 小时前
TDengine 选择函数 Max() 用户手册
大数据·数据库·物联网·时序数据库·tdengine·涛思数据
驾驭人生1 小时前
Asp .Net Core 系列:Asp .Net Core 集成 Hangfire+MySQL
数据库·mysql·.netcore
float_六七1 小时前
预编译SQL:安全与性能的双重保障
sql·安全·oracle