2013-02-08 38 views
1

的Oracle 10gPL/SQL - 提取文本,并结合如果重复

我的要求是:

  1. 选择每个部门
  2. 选择每个部门的各个项目(每个项目获得的其自己的行,但如果重复则合并)
  3. 选择每个不同部门和项目的每种颜色(如果重复,请选择最小编号)
  4. 选择每个不同部门的每个用户AND item(aggregate if多)

DB数据

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 
) 
; 

回答

0
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_)