Oracle 单行转多列

本贴最后更新于 1960 天前,其中的信息可能已经斗转星移

在数据库表设计中,经常会出现一对多关系,常用的处理办法有建立中间表和在“一”的那张表中的某个字段引用“多”的那张表,会以某符号分隔存储在表中。
但是在实际运用的过程中可能会用到分隔符引用的列需要转多行的需求,这时候我们一般会有两种处理办法:

  • 写函数方法
  • 正则表达式

比较而言第二种更加方便快捷,本文详细介绍第二种方式。

regexp_substr 函数

REGEXP_SUBSTR 函数格式如下:

function REGEXP_SUBSTR(String, pattern, position, occurrence, modifier)

__srcstr :需要进行正则处理的字符串

__pattern :进行匹配的正则表达式

__position :起始位置,从第几个字符开始正则表达式匹配(默认为 1)

__occurrence :标识第几个匹配组,默认为 1

__modifier :模式('i'不区分大小写进行检索;'c'区分大小写进行检索。默认为'c'。)

举个简单的例子,说明 REGEXP_SUBSTR 的用法

A:Students(学生)表

id code name books
1 1 张三 1,2,3

B:Book(图书)表

code name price
1 Java 从入门到精通 10
2 编译原理 10
2 颈椎康复指南 100

现需要统计出所有学生买图书的总价格
select user_id,user_name,

select stu.name, sum(k.price)
    (select name,
      REGEXP_SUBSTR(books, '[^,]+', 1, LEVEL) book
      --regexp_substr(str,reg,起始位置 第几次)
      from students
      CONNECT BY LEVEL <= LENGTH(books) - LENGTH(REGEXP_REPLACE(books, ',')) + 1
      and id = prior id
      and prior dbms_random.value is not null) stu
      --筛选掉空数据
      left join book k on k.code = stu.book

此次 sql 提取前 50 行执行时间为 1 点几秒,且数据量不大,下面为 sql 优化

select stu.name, sum(k.price)
    (select name,
      regexp_substr(books, '[^,]+', 1, level) book
      --regexp_substr(str,reg,起始位置 第几次)
      from students
      connect by level <= regexp_count(books, ',') + 1
      --regexp_count(teachers, ',') 统计字符串中,的数量
      and id = prior id
      and prior dbms_random.value is not null) stu
      --筛选掉空数据
      left join book k on k.code = stu.book

此次执行仅为 0.0 几秒,速度快了数十倍

CONNECT BY
  • 它相当于是一个递归的自连接,不断地把每层的连接结果叠加到结果集中。两层之间的连接条件和递归出口写在 CONNECT BY 中。在这里我们的数据并无父子关系,只是要让同一行数据重复出现,因此我们的连接的条件只用到了表的主键 id=PRIOR id, 此外再用 LEVEL 控制层数作为递归出口。但 ORACLE 有个检查,如果你有前后连接条件(id=PRIOR id),但是同一行数据再次出现,它就会报一个错:
  • --ERROR:
  • --ORA-01436: CONNECT BY loop in user data
  • --为了欺骗它,这里用了一个 PRIOR DBMS_RANDOM.VALUE, 因为 DBMS_RANDOM.VALUE 每次调用都返回不同结果,所以它认为两行数据不一样,所以不报错了。
  • Oracle

    Oracle(甲骨文)公司,全称甲骨文股份有限公司(甲骨文软件系统有限公司),是全球最大的企业级软件公司,总部位于美国加利福尼亚州的红木滩。1989 年正式进入中国市场。2013 年,甲骨文已超越 IBM,成为继 Microsoft 后全球第二大软件公司。

    103 引用 • 126 回帖 • 452 关注
  • 单行转多列
    1 引用 • 1 回帖
  • 逗号分隔
    1 引用 • 1 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...