0

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

我看到的是(配对)

#     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...,但这会破坏我的联系:

    错误-“没有更多数据可以从套接字读取”

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

  • 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)",

对不起,忘了包括那个。

4

1 回答 1

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之所以这样做,是varchar2因为wm_concat返回 aclob会导致连接org. 至少,它clob在 11gR2 中——我没有 wm_concat可用的 10g 实例,但我认为它会varchar2在早期版本中返回;如果是这样,cast则不需要,它更像是:

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

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


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


建议 Appleman1234 的替代sys_connect_by_path方法,用于相同的数据:

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 应该添加一个答案,我会删除这部分,因为他应该得到建议!反正我也想试试,以前看过,但是不记得了。。。

于 2013-01-23T18:35:33.463 回答