- PR -

複数行あるデータを1列1行内に結合して表示させたい

1
投稿者投稿内容
birdfly
会議室デビュー日: 2006/02/22
投稿数: 19
投稿日時: 2006-02-24 22:56
Access2002 + VBA
WindowsXP

自分なりに調べたのですが、検索しても不明だったため、
以下のような条件のとき、テーブルAの複数行あるデータを
テーブルBの1行内に表示させたいのです。

やりたいこと:TableAとTableBとTableCを結合したい
TableA
--------------------------
aCol1,aCol2,aCol3
1  1  2
2  1  4
3  1  1
4  2  3
5  2  5
--------------------------

TableB
--------------------------
bCol1,bCol2
1  あああ
2  いいい
3  ううう
4  えええ
5  おおお
--------------------------

TableC
--------------------------
cCol1,cCol2
1  AAA
2  BBB
3  CCC
4  DDD
5  EEE
--------------------------

表示したい結果:
--------------------------
bCol1,xCol2,xCol3
1  あああ  BBB、DDD、AAA
2  いいい  CCC、EEE
--------------------------

bCol1=aCol2のときに1行に表示したい。
aCol3=cCol1と結合する。
※xCol3は、1列内に表示

上記のようなことが通常のSQLで実現可能でしょうか?
わかりにくい説明で申し訳ないですけど、
よろしくお願いします。
とんくま
ベテラン
会議室デビュー日: 2005/08/02
投稿数: 56
お住まい・勤務地: 東京
投稿日時: 2006-02-25 23:58
再帰照会がすぐ頭に浮かびますが、DBMSによって書き方が違うのと、
Access2002をお使いということなので、使えないのではないかと思いますので、これは止めてJOINで実現することを考えて見ます。

以下のSQLはDB2では動きましたが、次の問題が有りますのでほんの参考程度に見てください。
1)xCol3が3行までの結合に制限される。(JOINを追加すれば、制限は大きく出来ますがJOIN数で制限されることには変わりない)
2)Access2002で動くか定かではない。

コード:
CREATE TABLE birdfly.TableA
(aCol1 INTEGER NOT NULL
,aCol2 INTEGER NOT NULL
,aCol3 INTEGER NOT NULL
);

INSERT INTO birdfly.TableA
VALUES
 (1,  1,  2)
,(2,  1,  4)
,(3,  1,  1)
,(4,  2,  3)
,(5,  2,  5)
;

CREATE TABLE birdfly.TableB
(bCol1 SMALLINT    NOT NULL
,bCol2 VARCHAR(10) NOT NULL
);

INSERT INTO birdfly.TableB
VALUES
 (1,  'あああ')
,(2,  'いいい')
,(3,  'ううう')
,(4,  'えええ')
,(5,  'おおお')
;

CREATE TABLE birdfly.TableC
(cCol1 INTEGER    NOT NULL
,cCol2 VARCHAR(5) NOT NULL
);

INSERT INTO birdfly.TableC
VALUES
 (1,  'AAA')
,(2,  'BBB')
,(3,  'CCC')
,(4,  'DDD')
,(5,  'EEE')
;


SELECT CHAR(bCol1)  AS "bCol1"
     , bCol2        AS "xCol2"
     , c1.cCol2
       || COALESCE(', '||c2.cCol2, '')
       || COALESCE(', '||c3.cCol2, '')
                    AS "xCol3"
  FROM birdfly.TableB
       INNER JOIN
       birdfly.TableA a1
       INNER JOIN
       birdfly.TableC c1
         ON  c1.cCol1 = a1.aCol3
         ON  bCol1 = a1.aCol2
       LEFT OUTER JOIN
       birdfly.TableA a2
       INNER JOIN
       birdfly.TableC c2
         ON  c2.cCol1 = a2.aCol3
         ON  bCol1 = a2.aCol2
         AND a2.aCol1 = a1.aCol1 + 1
       LEFT OUTER JOIN
       birdfly.TableA a3
       INNER JOIN
       birdfly.TableC c3
         ON  c3.cCol1 = a3.aCol3
         ON  bCol1 = a3.aCol2
         AND a3.aCol1 = a2.aCol1 + 1
 WHERE a1.aCol1
       = (SELECT MIN(aCol1)
            FROM birdfly.TableA am
           WHERE am.aCol2 = a1.aCol2);
------------------------------------------------------------------------------

bCol1  xCol2      xCol3              
------ ---------- -------------------
1      あああ     BBB, DDD, AAA      
2      いいい     CCC, EEE           

  2 record(s) selected.


unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2006-02-26 02:23
引用:

birdflyさんの書き込み (2006-02-24 22:56) より:
bCol1=aCol2のときに1行に表示したい。
aCol3=cCol1と結合する。
※xCol3は、1列内に表示


列をひとつの行にまとめることは、RDB の基本である第1正規化に反しますので、SQL の段階では、できればやらないほうが良いと思います。表示の都合で複数列を1行内にまとめて表示したいのならば、SQL では複数行の結果として取り出して、その後、キーブレークなどの手法を使ってまとめるほうが簡素になることも多いでしょう。
まあ、ケースバイケースになりますので、必ずこうしないといけない、というものでもないとは思います。しかし、RDBMS (の SQL)で表示プログラムを書くのはしんどいものです。
birdfly
会議室デビュー日: 2006/02/22
投稿数: 19
投稿日時: 2006-02-27 11:14
とんくま様、unibon様
回答ありがとうございます。

とんくま様
具体例のご提示ありがとうございます。
Access用に書き換えれば、とんくま様のやり方で実現できそうです。

unibon様
>SQL では複数行の結果として取り出して、その後、キーブレークなどの手法を使ってまとめるほうが簡素になることも多いでしょう。
キーブレークなどの手法というのは、どういった手法なのでしょうか?
プログラムで一旦とめるということでしょうか?
ググってみましたが、それらしいものが発見できませんでした。
簡単な例を教えていただけるとありがたいのですが。
すみません、無知なもので・・・。

よろしくお願いします。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2006-02-28 13:19
引用:

birdflyさんの書き込み (2006-02-27 11:14) より:
キーブレークなどの手法というのは、どういった手法なのでしょうか?
プログラムで一旦とめるということでしょうか?


SQL でつぎのところまで求めます。

SQL で求める中間結果:
--------------------------
bCol1,xCol2,xCol3
1  あああ  BBB
1  あああ  DDD
1  あああ  AAA
2  いいい  CCC
2  いいい  EEE
--------------------------

その後、SQL 外のプログラムで For ループなどを使って、bCol1,xCol2 の変わり目を見つけて、

表示したい結果:
--------------------------
bCol1,xCol2,xCol3
1  あああ  BBB、DDD、AAA
2  いいい  CCC、EEE
--------------------------
に変形するということです。

ただ、Microsoft Access とか使っていると、こうやって求めた結果を「コントロールソース」に指定できなくなっちゃうんで、どうしても無理やり SQL で全部やってしまいたいことも良くあります。
しかし、こういうのはツールの都合と考えて、あまり SQL で RDB の範疇を超えるような複雑な処理はしないほうが良いかな、と思うのですが、この辺はケースバイケースですね。
birdfly
会議室デビュー日: 2006/02/22
投稿数: 19
投稿日時: 2006-02-28 13:33
unibon様

丁寧な回答ありがとうございます。

>「コントロールソース」に指定できなくなっちゃうんで
そうなんです。「コントロールソース」に指定できなくなるとめんどいですよね?

結局、過去のデータからMAXを探して、
--------------------------
Col1,Col2,Col3
1  1  BBB、DDD、AAA
2  1  CCC、EEE
--------------------------
とテキスト(1200Byteぐらいで収まりそう)でも持つことにしました。

将来性を考えるとイケてないですが、一番簡易な回避方法なので・・・。
時間があれば、教えていただいた方法も検討させていただきたいと思います。
1

スキルアップ/キャリアアップ(JOB@IT)