Oracle SQL实现hist表多列转行(禁用CONNECT BY语法)
解决方案:将宽表多列转为行数据(无CONNECT BY)
好的,咱们来搞定这个需求——把hist表里的多组workN/salN列拆成每行对应一组的格式,而且不用CONNECT BY,这里有两个完全可行的方案:
方案1:使用UNION ALL(兼容所有Oracle版本)
这个方法兼容性拉满,不管你用的是哪个版本的Oracle都能跑通。核心思路就是把每组workN和salN分别作为单独的查询,再用UNION ALL把结果合并起来。
示例SQL代码:
SELECT emi_id, work1 AS work, sal1 AS sal FROM hist UNION ALL SELECT emi_id, work2 AS work, sal2 AS sal FROM hist UNION ALL SELECT emi_id, work3 AS work, sal3 AS sal FROM hist ... UNION ALL SELECT emi_id, work15 AS work, sal15 AS sal FROM hist ORDER BY emi_id, sal; -- 可选:按需求排序
注意:要把上面的...替换成从work4/sal4到work14/sal14的对应查询语句,确保15组都覆盖到。如果某些行的workN/salN为空,UNION ALL会保留这些行;如果想过滤空值,可以在每个子查询里加WHERE workN IS NOT NULL AND salN IS NOT NULL。
方案2:使用UNPIVOT(Oracle 11g及以上版本适用)
如果你的Oracle版本是11g或更高,用UNPIVOT会更简洁,代码量少很多,可读性也更强。这个语法专门用来处理宽表转长表的场景,而且可以同时处理成对的列(比如work和sal是一组)。
示例SQL代码:
SELECT emi_id, work, sal FROM hist UNPIVOT ( (work, sal) FOR work_sal_pair IN ( (work1, sal1) AS 'job_1', (work2, sal2) AS 'job_2', (work3, sal3) AS 'job_3', ... (work15, sal15) AS 'job_15' ) ) ORDER BY emi_id; -- 可选:按需求排序
这里的work_sal_pair是一个临时的列名,用来标识每组数据的来源(比如job_1对应第一组),你可以根据自己的习惯修改。同样,如果要过滤空值,可以在UNPIVOT后面加WHERE work IS NOT NULL AND sal IS NOT NULL。
两个方案都完全符合你的要求,不需要用到CONNECT BY语法,你可以根据自己的Oracle版本选择最合适的那个。
内容的提问来源于stack exchange,提问作者Tamil Mani
相关产品推荐
相关产品推荐

