Oracle 一对多关系 多行展示转一行展示

使用SQL进行数据列复制与转换,
文章描述了一个SQL查询需求,该查询用于将源数据中的某一列按照行编号rn复制并生成新列,例如列名2变为列名2(2)。通过使用MAX和CASEWHEN结合窗口函数row_number(),实现了根据rn值提取特定行的数据到新的列中。

最近收到一个小需求,长期不写SQL,颇为费了一番周折。

如图:

源数据类似于这样

列名1列名2
ac
ad
bc

转换后类似于这样

列名1列名2列名2(2)
acd
bc

因源数据有保密性要求,此处只提供SQL语句供大家参考:

select fybm,
       max(case when rn=1 then  htbm else null end) htbm1,
       max(case when rn=1 then  xyksrq else null end) xyksrq1,
       max(case when rn=1 then  xyjsrq else null end) xyjsrq1,
       max(case when rn=1 then  htztmc else null end) htztmc1,
       max(case when rn=2 then  htbm else null end) htbm2,
       max(case when rn=2 then  xyksrq else null end) xyksrq2,
       max(case when rn=2 then  xyjsrq else null end) xyjsrq2,
       max(case when rn=2 then  htztmc else null end) htztmc2,
       max(case when rn=3 then  htbm else null end) htbm3,
       max(case when rn=3 then  xyksrq else null end) xyksrq3,
       max(case when rn=3 then  xyjsrq else null end) xyjsrq3,
       max(case when rn=3 then  htztmc else null end) htztmc3,
       max(case when rn=4 then  htbm else null end) htbm4,
       max(case when rn=4 then  xyksrq else null end) xyksrq4,
       max(case when rn=4 then  xyjsrq else null end) xyjsrq4,
       max(case when rn=4 then  htztmc else null end) htztmc4,
       max(case when rn=5 then  htbm else null end) htbm5,
       max(case when rn=5 then  xyksrq else null end) xyksrq5,
       max(case when rn=5 then  xyjsrq else null end) xyjsrq5,
       max(case when rn=5 then  htztmc else null end) htztmc5,
       max(case when rn=6 then  htbm else null end) htbm6,
       max(case when rn=6 then  xyksrq else null end) xyksrq6,
       max(case when rn=6 then  xyjsrq else null end) xyjsrq6,
       max(case when rn=6 then  htztmc else null end) htztmc6
       --max(case when rn=7 then  htbm else null end) htbm7
from (
select fybm,
htbm,
xyksrq,
xyjsrq,
htztmc,
row_number() over(partition by fybm order by htbm desc ) rn from temp_20230209_lj a)
group by fybm

Oracle 数据库中,将一个字段中包含多个值的单行数据拆分成多行显示,是常见的数据清洗和处理需求。可以通过多种方式实现这一目标,包括使用 `CONNECT BY` 递归查询、`REGEXP_SUBSTR` 函数结合层级查询、以及使用 `XMLTABLE` 或 `JSON_TABLE`(适用于 Oracle 12c 及以上版本)等方法。 以下是一些常用的方法: ### 使用 `REGEXP_SUBSTR` 与 `CONNECT BY` 实现字段拆分 假设有一个表 `userinfomation`,其中 `city` 字段存储了多个城市名称,使用中文顿号“、”作为分隔符: ```sql SELECT TRIM(REGEXP_SUBSTR(city, '[^、]+', 1, LEVEL)) AS city_value FROM userinfomation CONNECT BY REGEXP_SUBSTR(city, '[^、]+', 1, LEVEL) IS NOT NULL AND PRIOR SYS_GUID() IS NOT NULL; ``` 该语句通过正则表达式 `[^、]+` 匹配非分隔符的连续字符,逐级提取每个值,并使用 `LEVEL` 控制递归层级,实现字段拆分[^2]。 ### 使用 `XMLTABLE` 实现字段拆分 如果使用的是 Oracle 11g R2 及以上版本,可以使用 `XMLTABLE` 来更高效地处理: ```sql SELECT x.city_value FROM userinfomation, XMLTABLE( 'for $i in tokenize(., "、") return <city>{$i}</city>' PASSING city COLUMNS city_value VARCHAR2(100) PATH 'text()' ) x; ``` 此方法利用 XQuery 的 `tokenize` 函数对字段进行分词拆分,返回 XML 格式的结果集,并通过 `COLUMNS` 子句提取每个拆分后的值[^3]。 ### 使用 `JSON_TABLE` 实现字段拆分(Oracle 12c+) 对于 Oracle 12c 及以上版本,也可以借助 `JSON_TABLE` 函数进行拆分: ```sql SELECT jt.city_value FROM userinfomation, JSON_TABLE( '["' || REPLACE(city, '、', '","') || '"]', '$[*]' COLUMNS (city_value VARCHAR2(100) PATH '$') ) jt; ``` 该方法通过将字符串换为 JSON 数组,再使用 `JSON_TABLE` 将数组展开为多行数据[^3]。 ### 注意事项 - 若字段中包含特殊字符(如逗号、括号等),需确保正则表达式正确义。 - 对于多字符分隔符(如 `,,` 或 `; `),应使用 `REGEXP_SUBSTR` 或 `REPLACE` 预处理为统一格式。 - 使用 `CONNECT BY` 时,建议结合 `PRIOR SYS_GUID()` 避免循环引用问题。 - 若数据量较大,建议评估性能影响,优先使用 `XMLTABLE` 或 `JSON_TABLE`。 以上方法均可根据实际字段内容和 Oracle 版本灵活选用。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值