0

複数のテーブルにまたがる非常に長いクエリがあり、所有者として 4 つの値 (名、ミドルネーム、姓 + 組織) を連結しています。他のすべての列は同じですが、所有者が複数あるため、集計したい行が複数あります。

私が見ているのは(ペアになっている)

#     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 は単に 1 つの所有者 (20 回の場合もある) を繰り返すだけで、目的の結果が得られません。

他にもいくつか試しましたが、うまくいきませんでした。私の現在のクエリは必要な数の行を生成していますが、2 番目の所有者を削除しているだけです。

クエリ全体をここに投稿するのが賢明かどうかはわかりません。これが役立つかどうか教えてください。


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だけで、これは完全には関係ありません。少なくとも、それは 11gR2 です。利用可能な10g インスタンスはありませんが 、以前のバージョンでは返されると思います。もしそうならは必要なく、次のようになります:castvarchar2wm_concatcloborgclobwm_concatvarchar2cast

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

あなたの価値がどこから来ているのかわからないので、これはおそらく単純化されています。また、問題が(問題または同等のものではなく)人にリンクされていて、問題に2つの問題がある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 が回答を追加する必要があります。この部分は削除します。とにかくやってみたかったのですが、前に見たことはありましたが、覚えていませんでした...

于 2013-01-23T18:35:33.463 に答える