2013-01-16 51 views
0

我有一个非常长的查询,跨多个表,我连接了四个值作为所有者(第一,中间名和最后一个名字+ org)。所有其他列是相同的,但有多个所有者,因此,我想要聚合多行。同一列中的多个值作为连接字符串聚合(10g)

我所看到的是(配对向下)

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

我想看到的是

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

注意事项:

  • 我无法创建功能(缺特权)
  • 使用Oracle 10g
  • 我试图CASE(COLLECT...但这杀死我的连接:

    Error- "No more data to read from socket"

    系统管理员,不知道为什么

  • 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: 

我相信可能会有一些更高层次的问题发挥作用。我的系统管理员没有回答“没有更多数据从套接字读取”的问题。这可能是另一回事吗?

我的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)", 

对不起,忘了包括。

+0

没有人回答,因为我错误地问了吗?我对唐的编辑有点困惑,可能他是这么想的,因为我的研究不够深入? – user1983682

+0

不,你问得很好,据我所知。有些人认为每个关键词都应该标注为代码,但我们到达这里的时间很长,但与您无关。人们可能只是不知道答案,就是这样。那么,尽我所能提高可读性并添加相关标签,因为我们正在谈论用SQL来做它,对吧? –

+0

是的,谢谢。 – user1983682

回答

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

...赋予相同的初始输出为您配对降取样:

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. 

我可以用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. 

replace只是放在名称,这是不完全相关的,我cast ing到varchar2,因为wm_concat返回clob这会导致问题级联org。至少,这是一个clob在11gR2 - 我没有一个10g实例与wm_concat可用,但我认为它在早期版本返回varchar2;如果是的话不需要cast,这将是更喜欢:

select issue_id, 
    replace(wm_concat(owner_name), ',', ', ') || ', ' || owner_org as owner 
from (
... 

我不知道您的org值从所以这可能是简化来了,我不知道你想什么如果org与某人(而非问题或您的等价物)相关联,并且问题有两个拥有不同org值的所有者,则会发生这种情况。


如果这不是让你更近,那么也许你可以发表你的查询的简化版本,与一些固定的数据替换长多台部分,展示你是如何尝试使用wm_concat反对;或者你自己版本的示例数据 - 构建,显示相同的行为。


替代sys_connect_by_path方法,建议Appleman1234,对于同样的数据:

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. 

如果你最终使用,Appleman1234应该添加一个答案,我会删除此部分,因为他应该得到建议它的功劳!无论如何,我想尝试它,我以前看过它,但没有记住它...

+0

@ user1983682 - 关于你的'字符串缓冲区太小'错误;你想用'wm_concat'连接多少个值?结果是一个10g的'varchar2',它将被限制在4k(或32k,但我认为是4k!);无论如何你仍然可以将它投射到1K。如果你有更多的值,你不介意丢失列表的末尾,你可以限制传递给它的行数,但是你必须设置一个足够低的数字,以确保你永远不会碰到限制。 –

+0

这只是最多三个人的第一个,中间和最后一个名字,如果我能解决的话,也许还是org。问题是我看到这个:Mark M. Majors,Mark M. Majors,Mark M. Majors ....“我不确定它为什么一遍又一遍地重复相同的值,可能会导致错误。 – user1983682

+0

@ user1983682 - 4k限制是针对总结果长度,而不是每个名称的长度;例如,如果您允许每个名称使用16个字符,那么您只能使用256个名称。三个人不应该成为一个问题。但重复看起来像是来自底层数据;如果你运行没有'wm_concat'的查询,你有没有重复? –

相关问题