oracle 中的字段数据行转列

oracle 中的字段数据行转列

1.oracle 中存在这样的数据,一个字段中,存放着多条数据的累积,但是是通过符号分割开,一般要用来关联的话,通常没有办法去拆分,无从下手,提供一个思路,

有着一个表,里面存在主键和单独的列,每个主键是唯一的,但是对应的col列的数据是一个的,或者是多个的,

准备 :建表

WITH TMP AS
 (SELECT 11 PKID, ',25989-21,25708-40,' COL
    FROM DUAL
  UNION ALL
  SELECT 12 PKID, '2598-21,258-40,258-41,,258-41,' COL
    FROM DUAL
  UNION ALL
  SELECT 13 PKID, '25-21,25708-40' COL
    FROM DUAL
  UNION ALL
  SELECT 14 PKID, '26' COL
    FROM DUAL
  UNION ALL
  SELECT 15 PKID, '27' COL
    FROM DUAL
  UNION ALL
  SELECT 16 PKID, '20,' COL
    FROM DUAL
  UNION ALL
  SELECT 17 PKID, '28,' COL
    FROM DUAL
  UNION ALL
  SELECT 18 PKID, ',222,333,444,555,666,' COL
    FROM DUAL)

第一步 :先找出对应的col列中有多少个分割的数据

WITH TMP AS
 (SELECT 11 PKID, ',25989-21,25708-40,' COL
    FROM DUAL
  UNION ALL
  SELECT 12 PKID, '2598-21,258-40,258-41,,258-41,' COL
    FROM DUAL
  UNION ALL
  SELECT 13 PKID, '25-21,25708-40' COL
    FROM DUAL
  UNION ALL
  SELECT 14 PKID, '26' COL
    FROM DUAL
  UNION ALL
  SELECT 15 PKID, '27' COL
    FROM DUAL
  UNION ALL
  SELECT 16 PKID, '20,' COL
    FROM DUAL
  UNION ALL
  SELECT 17 PKID, '28,' COL
    FROM DUAL
  UNION ALL
  SELECT 18 PKID, ',222,333,444,555,666,' COL
    FROM DUAL)
    
SELECT PKID, COL, LENGTH(COL) - LENGTH(REPLACE(COL, ',', '')) LT
          FROM TMP

第二步 :借用树状中的 level,没有实际意义,但是可以用来做动态的查询


WITH TMP AS
 (SELECT 11 PKID, ',25989-21,25708-40,' COL
    FROM DUAL
  UNION ALL
  SELECT 12 PKID, '2598-21,258-40,258-41,,258-41,' COL
    FROM DUAL
  UNION ALL
  SELECT 13 PKID, '25-21,25708-40' COL
    FROM DUAL
  UNION ALL
  SELECT 14 PKID, '26' COL
    FROM DUAL
  UNION ALL
  SELECT 15 PKID, '27' COL
    FROM DUAL
  UNION ALL
  SELECT 16 PKID, '20,' COL
    FROM DUAL
  UNION ALL
  SELECT 17 PKID, '28,' COL
    FROM DUAL
  UNION ALL
  SELECT 18 PKID, ',222,333,444,555,666,' COL
    FROM DUAL)
SELECT PKID,
       COL,
       INSTR(COL, ',', B.LL - 1), -- 对应出现的开始位置
       INSTR(COL, ',', B.LL), -- 对应出现的结束位置
  FROM (SELECT PKID, COL, LENGTH(COL) - LENGTH(REPLACE(COL, ',', '')) LT
          FROM TMP) A,
       (SELECT LEVEL LL FROM DUAL CONNECT BY LEVEL <= 1000) B
 WHERE A.LT >= B.LL
 ORDER BY PKID

第三步 :通过找到对应的位置后,开始截取

WITH TMP AS
 (SELECT 11 PKID, ',25989-21,25708-40,' COL
    FROM DUAL
  UNION ALL
  SELECT 12 PKID, '2598-21,258-40,258-41,,258-41,' COL
    FROM DUAL
  UNION ALL
  SELECT 13 PKID, '25-21,25708-40' COL
    FROM DUAL
  UNION ALL
  SELECT 14 PKID, '26' COL
    FROM DUAL
  UNION ALL
  SELECT 15 PKID, '27' COL
    FROM DUAL
  UNION ALL
  SELECT 16 PKID, '20,' COL
    FROM DUAL
  UNION ALL
  SELECT 17 PKID, '28,' COL
    FROM DUAL
  UNION ALL
  SELECT 18 PKID, ',222,333,444,555,666,' COL
    FROM DUAL)
SELECT PKID,
       COL,
       INSTR(COL, ',', B.LL - 1), -- 对应出现的开始位置
       INSTR(COL, ',', B.LL), -- 对应出现的结束位置
       REPLACE(SUBSTR(COL, INSTR(COL, ',', B.LL - 1), INSTR(COL, ',', B.LL)),
               ',',
               '') TEXT, -- 截取后的数据中不包含符号
       SUBSTR(COL, INSTR(COL, ',', B.LL - 1), INSTR(COL, ',', B.LL)) AS TEXTS -- 截取后所有的数据都在这
  FROM (SELECT PKID, COL, LENGTH(COL) - LENGTH(REPLACE(COL, ',', '')) LT
          FROM TMP) A,
       (SELECT LEVEL LL FROM DUAL CONNECT BY LEVEL <= 1000) B
 WHERE A.LT >= B.LL
 ORDER BY PKID

第四步 :如果需要,将为空的,或者是为单独符号的都剔除

WITH TMP AS
 (SELECT 11 PKID, ',25989-21,25708-40,' COL
    FROM DUAL
  UNION ALL
  SELECT 12 PKID, '2598-21,258-40,258-41,,258-41,' COL
    FROM DUAL
  UNION ALL
  SELECT 13 PKID, '25-21,25708-40' COL
    FROM DUAL
  UNION ALL
  SELECT 14 PKID, '26' COL
    FROM DUAL
  UNION ALL
  SELECT 15 PKID, '27' COL
    FROM DUAL
  UNION ALL
  SELECT 16 PKID, '20,' COL
    FROM DUAL
  UNION ALL
  SELECT 17 PKID, '28,' COL
    FROM DUAL
  UNION ALL
  SELECT 18 PKID, ',222,333,444,555,666,' COL
    FROM DUAL)
SELECT PKID,
       COL,
       INSTR(COL, ',', B.LL - 1),
       INSTR(COL, ',', B.LL),
       REPLACE(SUBSTR(COL, INSTR(COL, ',', B.LL - 1), INSTR(COL, ',', B.LL)),
               ',',
               '') TEXT,
       SUBSTR(COL, INSTR(COL, ',', B.LL - 1), INSTR(COL, ',', B.LL)) AS TEXTS
  FROM (SELECT PKID, COL, LENGTH(COL) - LENGTH(REPLACE(COL, ',', '')) LT
          FROM TMP) A,
       (SELECT LEVEL LL FROM DUAL CONNECT BY LEVEL <= 1000) B
 WHERE A.LT >= B.LL
   AND REPLACE(SUBSTR(COL, INSTR(COL, ',', B.LL - 1), INSTR(COL, ',', B.LL)),
               ',',
               '') IS NOT NULL
 ORDER BY PKID

结束,将对应的临时表换成你对应的表,需要的字段添加即可

### Oracle 数据库字段行转列实现方法 在处理Oracle数据库中的数据转换需求时,特别是当涉及到将多个字段数据从行形式转化为列形式展示时,可以采用`PIVOT`函数来达成目的。此功能允许基于特定条件聚合数据并将其重新排列成更易于分析的形式[^1]。 对于较为复杂的场景,除了基本的`PIVOT`外,还可以组合使用其他SQL特性如子查询、连接操作以及聚合函数等共同构建满足业务逻辑要求的结果集。下面提供了一个简单的例子用于说明如何利用这些工具执行多字段行到列的变化: 假设存在一张记录员工技能水平评估得分情况的表格SKILLS_SCORES,其中包含EMPLOYEE_ID(雇员ID)、SKILL_NAME(技能名称)和SCORE(分数)。目标是从这张表里提取每位员工针对不同技能所获得的具体评分,并按照单一行内显示的方式呈现出来。 ```sql SELECT * FROM ( SELECT EMPLOYEE_ID, SKILL_NAME, SCORE FROM SKILLS_SCORES ) PIVOT( MAX(SCORE) FOR SKILL_NAME IN ('Java' AS JAVA_SKILL,'Python' AS PYTHON_SKILL,'C++' AS CPP_SKILL) ); ``` 上述命令会创建一个新的视图,在这里每个员工对应一条记录,而原先作为单独条目存储的各项技能成绩被横向展开成为独立列项。注意这里的IN子句指定了要转化的具体项目及其对应的别名;实际应用中可根据具体情况进行调整以适应不同的输入源结构。 为了进一步增强灵活性和支持动态定义待转换的目标列表,可考虑编写PL/SQL程序或借助外部应用程序接口生成相应的SQL脚本片段再加以执行。这种方式特别适用于那些事先无法确切知道所有可能值的情况之下。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值