Pl/SQL - 提取文本并在重复时合并

Posted

技术标签:

【中文标题】Pl/SQL - 提取文本并在重复时合并【英文标题】:Pl/SQL - Extract text and combine if duplicates 【发布时间】:2013-02-08 21:17:37 【问题描述】:

甲骨文 10g

我的要求是:

    选择每个部门 选择每个部门的每个单独的项目(每个项目都有自己的行,但如果重复则合并) 选择每个不同部门和项目的每种颜色(如果重复,请选择最小的数字) 选择每个不同部门和项目的每个用户(如果有多个则聚合)

数据库数据

Department    Item_List                  Color       User
Research      Item 1                    1. Blue      John
Research      Item 1;Item 2             2. Blue      Mike
Research      Item 1;Item 2; Item 3     1. Red       Steve
Research      Item 2                    1. Purple    John
Research      Item 1;Item 4             2. Red       Bill
Ops           Item 1;Item 2             3. Silver    John
Ops           Item 1;Item 3             3. Silver    Mike
Ops           Item 4                    4. Yellow    Mark

预期结果

Department    Item_List         Color         User
Research        Item 1         1. Blue       John, Mike
Research        Item 2         1. Blue       Mike
Research        Item 1         1. Red        Steve, Bill
Research        Item 2         1. Red        Steve
Research        Item 3         1. Red        Steve
Research        Item 2         1. Purple     John
Research        Item 4         1. Red        Bill
Ops             Item 1         3. Silver     John, Mike
Ops             Item 2         3. Silver     John
Ops             Item 3         3 Silver      Mike
Ops             Item 4         4. Yellow     Mark

我正在使用以下 SQL,但它不起作用:

with data as 
(
select
DEPARTMENT, 
ITEM_LIST,
(length(ITEM_LIST)-length(replace(ITEM_LIST,';','')))+1 cnt,
MIN(Color) as Color,
wm_concat(USER) as USER
from DataBase_Table
Group by 
DEPARTMENT, 
ITEM_LIST
)
select 
DEPARTMENT
ITEM_LIST,
Color,
User
from
(
select distinct 
DEPARTMENT,
ltrim(regexp_substr(ITEM_LIST,'[^;]+',1,level)) ITEM_LIST, 
Color,
level,
User
from data
connect by level <= cnt
order by DEPARTMENT
)
;

【问题讨论】:

【参考方案1】:
with 
   t1 as (
      select 
         department, 
         trim(regexp_substr(item_list, '[^;]+', 1, occ)) as item,
         to_number(regexp_substr(color, '^\d+')) as color_no, 
         regexp_replace(color, '^\d+(.*)$', '\1') as color_name, 
         user_
      from 
         (
            select level as occ from dual 
            connect by level <= (select max(length(item_list)) from source)
         ), 
         source
      where regexp_substr(item_list, '[^;]+', 1, occ) is not null
   )
select 
   department, 
   item,
   color, 
   listagg(user_, ',') within group (order by user_)
from
   (
      select 
         min(color_no)||color_name as color, 
         color_name
      from t1
      group by color_name
   ) 
   natural join t1 
group by 
   department, 
   item,
   color
order by 1 desc, 2, 3

SQLFiddle

在 Oracle 10 中,您应该使用wm_concat(distinct user_) 而不是listagg(user_, ',') within group (order by user_)

【讨论】:

以上是关于Pl/SQL - 提取文本并在重复时合并的主要内容,如果未能解决你的问题,请参考以下文章

将PL/SQL代码封装在机灵的包中

Windows 64位 安装Oracle instantclient 官方绿色版和PL/SQL Developer 总结

在 PL/SQL 中合并行

在使用 Entity Framework 数据库优先在表上插入行之前,如何从 PL/SQL 执行触发器?

如何在选择语句的“NOT IN”子句中使用逗号分隔的字符串列表作为 pl/sql 存储的函数参数

PL/SQL developer连接oracle出现“ORA-12154:TNS:could not resolve the connect identifier specified”问题的解决(代码