1

既存のテーブルと同じデータですが、非正規化された新しいテーブルのデータを準備しようとしています。私は単純なシナリオを持っていますが、私の心は結果を返す最も効率的な方法で空白を描いています

これは、次の単純化されたシナリオに基づいています。

Table X   | Table y
id        | id    Identifier  Value
123       | 123   1           A
          | 123   2           B

テーブル XI のその他のフィールドに加えて、クエリで次の値を返す必要があります。

123 A B

私は考えました:

ソリューション 1

select 
id,
(select Value...),
(select Value...)...

解決策 2:

select id,
y1.Value,
y2.Value
from x, y y1, y y2...

解決策 3: PL/SQL を使用してカーソルを反復処理する

解決策 4: y を 2 つのテーブル identifier1 と identifier2 (潜在的にトリガーを使用) に抽出し、代わりにこれらのテーブルをクエリ内で結合する

これらのソリューションのそれぞれには、何らかの理由で大きな欠点があり、一言でこれを解決するためのコンセプトを思い出させることができると確信しています。

4

1 に答える 1

5

何かが欠けていない限り、あなたはデータをピボットしようとしています。これを行うにはいくつかの方法があります。

集計関数とCASE式を使用できます。

select x.id,
  max(case when y.identifier = 1 then y.value end) Value1,
  max(case when y.identifier = 2 then y.value end) Value2
from tablex x
left join tabley y
  on x.id = y.id
group by x.id

デモで SQL Fiddle を参照してください

Oracle のバージョンに応じて、次のPIVOT関数を使用できます。

select id,
  Value1,
  Value2
from
(
  select x.id, y.identifier, y.value
  from tablex x
  left join tabley y
    on x.id = y.id
) 
pivot
(
  max(value)
  for identifier in ('1' as Value1, '2' as Value2)
) piv

デモで SQL Fiddle を参照してください

複数回参加できます:

select x.id,
  y1.value Value1,
  y2.value Value2
from tablex x
left join tabley y1
  on x.id = y1.id
  and y1.identifier = 1
left join tabley y2
  on x.id = y2.id
  and y2.identifier = 2

SQL Fiddle with Demoを参照してください。

動的なソリューションを探している場合は、sys_refcursor を使用してプロシージャを作成できます。

CREATE OR REPLACE procedure dynamic_pivot(p_cursor in out sys_refcursor)
as
    sql_query varchar2(8000) := 'select x.id ';

    begin
        for x in (select distinct identifier from tabley order by 1)
        loop
            sql_query := sql_query ||
                ' , max(case when y.identifier = '||x.identifier||' then y.value else null end) as Value'||x.identifier;

                dbms_output.put_line(sql_query);
        end loop;

        sql_query := sql_query || ' from tablex x
                                    left join tabley y
                                      on x.id = y.id
                                    group by x.id';
        dbms_output.put_line(sql_query);

        open p_cursor for sql_query;
    end;
/

これらのソリューションでは、値ごとに別々の列に結果が表示されます。単一の列にデータが必要な場合は、次を使用できますLISTAGG()

select x.id,
  listagg(y.value, ' ') within group (order by y.id) as Value
from tablex x
left join tabley y
  on x.id = y.id
group by x.id

デモで SQL Fiddle を参照してください

于 2013-02-28T20:46:02.990 に答える