2011-07-22 9 views
0

は(実際にデータがXMLである、ID_A、ID_B、タイプが実際の整数である)私は、次の表を持っていると言う:この表を変換してください。 "group by"のような "coalasce"のようなもので?

id_a id_b type  data 
-----+------+--------+-------- 
    1  1  X  X1 
    1  1  Y  Y1 
    7 17  Y  Y2 
    7 99  X  X2 
    9 20  Z  Z1 

ID_A、ID_Bとタイプの組み合わせはユニークです。 私が書き込むプログラムは、私が気にする型のリストを入力として取得します。このリストは、Xが含まれていることを言うとY.は今、私は次のような結果に終わるいくつかのSQL-マジックをやってみたい。すなわち

id_a id_b  X  Y 
-----+------+--------+-------- 
    1  1  X1  Y1 
    7  17  NULL  Y2 
    7  99  X2  NULL 

:私はID_AとID_B、リストのすべてのデータを含む行をしたいです列内のデータ

私は、次の表で終わる自分でクエリを見つけることができました:

table: 
id_a id_b data_x data_y 
-----+------+--------+-------- 
    1  1  X1  NULL 
    1  1  NULL  Y1 
    7 17  NULL  Y2 
    7 99  X2  NULL 

クエリを:

select 
    id_a, 
    id_b, 
    case when type = 'X' then data 
    end data_x, 
    case when type = 'Y' then data 
    end data_y, 
from 
    mytable 
order by 
    id_a,id_b 

この表では、それが

    ことが保証されています
  • data_xまたはdata_yの最大値はNULLでなくてもかまいません(NULLもOKですが、もちろんで簡単にフィルタリングできます))
  • data_xとdata_yは、それぞれid_aとid_bの組み合わせで一意です。私は今、その後select coalesce(case ... data_y),coalesce(case ... data_y) from ... group by id_a,id_bを行うことができれば

そして、私は私がなりたい場所を、私は信じているだろうが、残念ながら合体は、集計関数が、スカラー関数ではありません。

私のクライアントアプリケーション(Javaで書かれています)では、もちろん行をマージすることはできますが、行をマージすることはできますが、これはあまりエレガントではありません。これを解決するための「かなり」の方法がありますか?

...

答えて

1

をこれは、あなたが望む結果を与える:

create table myTable (
    id_a int not null, 
    id_b int not null, 
    type char(1) not null, 
    data varchar(10), 
    unique (id_a, id_b, type) 
); 

insert into myTable values (1, 1, 'X', 'X1'); 
insert into myTable values (1, 1, 'Y', 'Y1'); 
insert into myTable values (7, 17, 'Y', 'Y2'); 
insert into myTable values (7, 99, 'X', 'X2'); 
insert into myTable values (9, 20, 'Z', 'Z1'); 

select coalesce(X.id_a, Y.id_a) as id_a, coalesce(X.id_b, Y.id_b) as id_b, 
     X.data as X, Y.data as Y 
    from (select * from myTable where type = 'X') X 
     full outer join (select * from myTable Y where type = 'Y') Y 
      on X.id_a = Y.id_a and X.id_b = Y.id_b 

結果

ID_A ID_B X Y 
---- ---- ---- ---- 
    1 1 X1 Y1 
    7 17 NULL Y2 
    7 99 X2 NULL 
+0

かなりスマート、はい...あなたとソリューションの間の厳しい決断。今の私はあなたのことを選んだ:-)。 – yankee

2

利用MAXを私は、DB2 V9.7を使用していますが、私はポータブルソリューションを好むだろうか?

SELECT 
    id_a, 
    id_b, 
    MAX(CASE WHEN type = 'X' THEN data END) AS data_x, 
    MAX(CASE WHEN type = 'Y' THEN data END) AS data_y 
FROM 
    myTable 
GROUP BY 
    id_a, 
    id_b 

EDIT

あなたは、集計関数を使用できない場合は、このようなものは、あなたのニーズに合うのでしょうか?

SELECT 
    map.id_a, 
    map.id_b, 
    myTableX.data AS data_x, 
    myTableY.data AS data_y 
FROM 
    (SELECT id_a, id_b FROM myTable GROUP BY id_a, id_b) AS map 
LEFT JOIN 
    myTable AS myTableX 
    ON myTalbeX.id_a = map.id_a 
    AND myTableX.id_b = map.id_b 
    AND myTableX.type = 'X' 
LEFT JOIN 
    myTable AS myTableY 
    ON myTalbeY.id_a = map.id_a 
    AND myTableY.id_b = map.id_b 
    AND myTableY.type = 'Y' 
+0

良い考えですが、「各引数は、CLOB、DBCLOB、BLOB、ROWID、またはXML以外の組み込みデータ型の値を返す式でなければなりません。残念なことに私の "データ"列はXML型です.-(( – yankee

+0

良い解決策、ありがとう:-)。私は最終的にFransの解決策を解決しましたが、私は両方ともうまくやっていると思います... – yankee

+0

私はDB2上であり、これは私がそれに近づく方法について(改訂版の回答)です - 代わりにCTEテーブル参照の(ほとんどの場合、習慣の力によって)。 –

0

異なるレコードに表示されるデータを結果セットの同じレコードに持っていくには、まだ何かを行う必要があります。これを行うには、集計関数を使用する必要があります。最大、最小。私はDB2にアクセスすることはできませんが、多くの点でOracleとかなり似ています。次はOracle上でうまく動作します。

with tmp as 
(select 1 id_a, 1 id_b, 'X' type_, 'X1' data_ from dual union 
    select 1 id_a, 1 id_b, 'Y' type_, 'Y1' data_ from dual union 
    select 7 id_a, 17 id_b, 'Y' type_, 'Y2' data_ from dual union 
    select 7 id_a, 99 id_b, 'X' type_, 'X2' data_ from dual union 
    select 9 id_a, 20 id_b, 'Z' type_, 'Z1' data_ from dual) 
select distinct 
     id_a, 
     id_b, 
     max(decode(type_, 'X', data_, null)) data_x, 
     max(decode(type_, 'Y', data_, null)) data_y 
    from tmp 
group by id_a, id_b 

EDIT:非集計バージョンについては 、あなたはこの使用することができます。

with tmp as 
    (select 1 id_a, 1 id_b, 'X' type_, 'X1' data_ from dual union 
     select 1 id_a, 1 id_b, 'Y' type_, 'Y1' data_ from dual union 
     select 7 id_a, 17 id_b, 'Y' type_, 'Y2' data_ from dual union 
     select 7 id_a, 99 id_b, 'X' type_, 'X2' data_ from dual union 
     select 9 id_a, 20 id_b, 'Z' type_, 'Z1' data_ from dual) 
    select nvl(x.id_a, y.id_a) id_a, nvl(x.id_b, y.id_b) id_b, x.data_, y.data_ 
     from tmp x 
      full outer join tmp y 
      on ( x.id_a = y.id_a 
       and x.id_b = y.id_b 
       and x.type_ = 'X' 
       and y.type_ = 'Y') 
where x.data_ like 'X%' or y.data_ like 'Y%' 
+0

はい、私は集計関数が必要ですが、残念ながらDemsの答えとほぼ同じです。データはXML型であるため、max()は使用できません。 – yankee

+0

改訂されたアンサーでは、完全な外部結合の前に 'tmp'テーブルを' X 'に、または 'Y' *にフィルタリングする必要があります。現在、joinは 'tmp x'にすべてを含めることを許可し、あなたの述語に基づいて' tmp y'にのみ参加します。また、where句は、 'x.data_'または' y.data_'が 'NULL'であるレコードをすべて削除します。 – MatBailie

+0

こんにちは@Dems。あなたはそれをそのまま実行しようと思うかもしれません。それは私のためにうまく動作します。 'tmp x'と' tmp y'の 'X 'または' Y'だけのフィルタリングは 'on'節で行われることに注意してください。 – Gabe

関連する問題