从同一列聚合多个值作为连接字符串(10g)

use*_*682 0 sql aggregate oracle10g

我有一个很长的查询,跨多个表,我将四个值连接为所有者(名字,中间名和姓氏+组织).所有其他列都是相同的,但有多个所有者,因此,我想聚合多行.

我所看到的是(配对)

#     Owner
1     Sam Smith, AAA
2     Stan Bird, BBB
2     Nancy Bird, BBB
3     Mike Owen, CCC
Run Code Online (Sandbox Code Playgroud)

我想看到的是

#     Owner
1     Sam Smith, AAA
2     Stan Bird, Nancy Bird, BBB
3     Mike Owen, CCC
Run Code Online (Sandbox Code Playgroud)

注意事项:

  • 我无法创建功能(缺少权限)
  • 使用Oracle 10g
  • 我试过CASE(COLLECT...但这会杀死我的联系:

    错误 - "无法从套接字读取更多数据"

    SysAdmin,不知道为什么

  • WM_CONCAT只是重复一个所有者(有时是20次)并且没有给出所需的结果.

我尝试过其他一些事情,没有运气.我当前的查询产生了所需的行数,但只是砍掉了第二个所有者.

我不确定在这里发布整个查询是否明智.请告诉我这是否有帮助.


更新2012-01-29

wm_concat之前我使用不正确,但是当我使用它时,我收到此错误:

 ORA-06502: PL/SQL: numeric or value error: character string buffer too
 small ORA-06512: at "WMSYS.WM_CONCAT_IMPL", line 30
 06502. 00000 -  "PL/SQL: numeric or value error%s"
 *Cause:    
 *Action:
Run Code Online (Sandbox Code Playgroud)

我相信可能会有一些更高层次的问题.我的系统管理员对"无法从套接字读取数据"问题没有答案.这可能是另一个.

我的SQL知识是有限的,并且随着查询的长度和复杂性,我似乎无法实现sys_connect_by_path; 完全是我自己的错.

抱歉延迟回复.我被拉开以完成另一项任务.谢谢你的帮助.感谢ShadowWizard的赏金.

编辑
这是我wm_concat在当前实例中使用的方式:

 replace(cast(wm_concat(PERSON.MASTER_PERSON_FIRST_NAME   || ' '   ||
 PERSON.MASTER_PERSON_MIDDLE_INITIAL   || ' '   ||
 PERSON.MASTER_PERSON_LAST_NAME   || ','   || ' '   ||
 ORGANIZATION.MASTER_ORG_NAME) AS VARCHAR2(1000 BYTE)), ',', ', ') AS
 "Owner(s)",
Run Code Online (Sandbox Code Playgroud)

对不起,忘了把它包括在内.

Ale*_*ole 5

不知道为什么wm_concat不适合你,但我怀疑你有错误的水平或奇怪的分组.

如果我设置了一些虚拟数据:

create table issues (id number);

create table owners (id number, first varchar2(10), middle varchar2(10),
    last varchar2(10), org varchar2(3));

create table issue_owners (issue_id number, owner_id number);

insert into issues (id) values (1);
insert into issues (id) values (2);
insert into issues (id) values (3);

insert into owners (id, first, middle, last, org)
    values (11, 'Sam', null, 'Smith', 'AAA');
insert into owners (id, first, middle, last, org)
    values (12, 'Stan', null, 'Bird', 'BBB');
insert into owners (id, first, middle, last, org)
    values (13, 'Nancy', null, 'Bird', 'BBB');
insert into owners (id, first, middle, last, org)
    values (14, 'Mike', null, 'Owen', 'CCC');

insert into issue_owners (issue_id, owner_id) values (1, 11);
insert into issue_owners (issue_id, owner_id) values (2, 12);
insert into issue_owners (issue_id, owner_id) values (2, 13);
insert into issue_owners (issue_id, owner_id) values (3, 14);
Run Code Online (Sandbox Code Playgroud)

...它提供与配对样本相同的初始输出:

column issue_id format 9 heading "#"
column owner format a50 heading "Owner"

select i.id as issue_id,
    o.first
        || case when o.middle is null then null else ' ' || o.middle end
        || ' ' || last || ', ' ||o.org as owner
from issues i
left join issue_owners io on io.issue_id = i.id
left join owners o on o.id = io.owner_id
order by issue_id, owner;

 # Owner
-- --------------------------------------------------
 1 Sam Smith, AAA
 2 Nancy Bird, BBB
 2 Stan Bird, BBB
 3 Mike Owen, CCC

4 rows selected.
Run Code Online (Sandbox Code Playgroud)

我可以wm_concat用来聚合名称:

select issue_id,
    replace(cast(wm_concat(owner_name) as varchar2(4000)), ',', ', ')
        || ', ' || owner_org as owner
from (
    select i.id as issue_id,
        o.first
            || case when o.middle is null then null else ' ' || o.middle end
            || ' ' || last as owner_name,
        o.org as owner_org
    from issues i
    left join issue_owners io on io.issue_id = i.id
    left join owners o on o.id = io.owner_id
)
group by issue_id, owner_org
order by issue_id, owner;

 # Owner
-- --------------------------------------------------
 1 Sam Smith, AAA
 2 Stan Bird, Nancy Bird, BBB
 3 Mike Owen, CCC

3 rows selected.
Run Code Online (Sandbox Code Playgroud)

replace只是把空间名字,这并不完全相关之间,而我cast荷兰国际集团到varchar2,因为wm_concat回报clob,而存在串接org.至少,它是clob11gR2中的一个- 我没有wm_concat可用的10g实例 ,但我认为varchar2在早期版本中返回; 如果是这样的话cast就不需要了,它更像是:

select issue_id,
    replace(wm_concat(owner_name), ',', ', ') || ', ' || owner_org as owner
from (
...
Run Code Online (Sandbox Code Playgroud)

我不确定你的org价值来自哪里所以这可能是简化的,我不知道你想要发生什么,如果org它与一个人有关(而不是一个问题或你的等同物),而且问题有两个拥有不同org价值观的业主


如果这没有让你更近,那么也许你可以发布你的查询的简化版本,用一些固定数据替换长多表部分,并显示你如何使用wm_concat它; 或您自己的示例数据构建版本,显示相同的行为.


sys_connect_by_pathAppleman1234建议的替代方法,对于相同的数据:

select issue_id,
    ltrim(max(sys_connect_by_path(owner_name, ', '))
        keep (dense_rank last order by curr), ', ')
        || ', ' || owner_org as owner
from (
    select issue_id,
        owner_name,
        owner_org,
        row_number() over (partition by issue_id order by owner_name) as curr,
        row_number() over (partition by issue_id order by owner_name) - 1 as prev
    from (
        select i.id as issue_id,
            o.first
                || case when o.middle is null then null else ' ' || o.middle end
                || ' ' || last as owner_name,
            o.org as owner_org
        from issues i
        left join issue_owners io on io.issue_id = i.id
        left join owners o on o.id = io.owner_id
    )
)
group by issue_id, owner_org
connect by prev = prior curr and issue_id = PRIOR issue_id
start with curr = 1;

 # Owner
-- --------------------------------------------------
 1 Sam Smith, AAA
 2 Nancy Bird, Stan Bird, BBB
 3 Mike Owen, CCC

3 rows selected.
Run Code Online (Sandbox Code Playgroud)

如果你最终使用它,Appleman1234应该添加一个答案,我将删除这部分,因为他应该得到建议的信誉!无论如何我想尝试一下,我以前见过它但是没记得它......