2

3つのテーブルTa、Tb、Tcが与えられます:

Ta(ID, Field1)
Tb(ID, Field2)
Tc(ID, Field3)

与えられたデータの例:

Ta
ID Field1
---------
1  A
1  B

Tb
ID Field2
---------
1  C
1  D
2  E

Tc
ID Field3
---------
1  F
2  G
2  H

質問: このデータを結合して返すにはどうすればよいですか?

ID Field1 Field2 Field3
-----------------------
1  A      C      F
1  B      D      NULL
2  NULL   E      G
2  NULL   NULL   H

外部結合でこれを達成できると思いましたが、そうではないようです。行が重複しないようにすべての情報を戻す限り、グループ化の順序は実際には重要ではありません。

明確にするために。結果セットが最小行数のすべてのデータを返す限り、どの組み合わせを取得してもかまいません。これが私がやろうとしていることのより現実的な例です:

人を与えられて、彼をジョンと呼んでください。彼は2つの電話番号と3つの電子メールアドレスを持っています:

PID  Email
---------
John john@test.com
John john@mail.com
John john@john.com

PID  Tel
--------
John 011
John 022

戻りたい:

PID  Email         Tel
----------------------
John john@test.com 011
John john@mail.com 022
John john@john.com NULL
4

2 に答える 2

3

あなたは次のことに近づくことができます:

select coalesce(ta.id, tb.id, tc.id), ta.field1, tb.field2, tc.field3
from (select ta.*, row_number() over (partition by id order by (select NULL)) as seqnum
      from ta
     ) ta full outer join
     (select tb.*, row_number() over (partition by id order by (select NULL)) as seqnum
      from tb
     ) tb
     on ta.id = tb.id and
        ta.seqnum = tb.seqnum
     (select tc.*, row_number() over (partition by id order by (select NULL)) as seqnum
      from tc
     ) tc
     on coalesce(ta.id, tb.id) = tc.id and
        coalesce(ta.seqnum, tb.seqnum) = tc.seqnum
group by coalesce(ta.id, tb.id, tc.id),
         coalesce(ta.seqnum, tb.seqnum, tc.seqnum)
order by 1, 2

ただし、私のコメントでは、テーブル内の行の順序は保証されていないため、期待した順序で表示されない場合があります。サンプルデータでは、次のものを使用できます。

over (partition by id order by field<n>)

フィールドが順序を定義する場合

于 2012-10-02T14:08:35.713 に答える
3

これは、CTEとUnionを使用し、MINを使用してnullを除外する別の方法です。順序を保証するものではありませんが、IDがすべて存在する限り、気にしないと言っているので。

SQLフィドルはこちら

WITH TaRanked AS
(
  SELECT ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Field1) as Rnk, ID, Field1
  FROM Ta
),
TbRanked AS
(
  SELECT ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Field2) as Rnk, ID, Field2
  FROM Tb
),
TcRanked AS
(
  SELECT ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Field3) as Rnk, ID, Field3
  FROM Tc
),
TUnion AS
(
    SELECT Rnk, ID, Field1, NULL AS Field2, NULL AS Field3 
        FROM TaRanked 
    UNION ALL
    SELECT Rnk, ID, NULL, Field2, NULL 
        FROM TbRanked 
    UNION ALL
    SELECT Rnk, ID, NULL, NULL, Field3 
        FROM TcRanked 
)
SELECT ID, MIN(Field1), MIN(Field2), MIN(Field3)
  FROM TUnion
  GROUP BY ID, Rnk
  ORDER BY ID, Rnk

結果は

1   A       C       F
1   B       D       (null)
2   (null)  E       G
2   (null)  (null)  H
于 2012-10-02T14:26:51.600 に答える