- ベストアンサー
テーブルのマージSQLで複数項目を出力する方法
- AテーブルとBテーブルをマージさせ、社員番号と内容を日付順に並べ替える方法について教えてください。
- UNIONを使用することで、異なる項目を持つテーブルをマージさせることができますが、所属、時間、結果、理由の項目を全て出力する方法はありますか?
- UNIONの場合、項目が異なるとエラーとなってしまう可能性があります。どのように記載すれば良いでしょうか?
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
そもそもがUNIONの用途として正しくない気がしますしね。 複数のテーブルの同一キーのデータを簡単に取れないというのは、設計がよくないのではないかという気がします。 >1つ1つNULLを設定するのは難しいかと、、、 とありますが、ただ面倒だということですよね? ひとつひとつ項目を列挙していくだけなので難しいことはないと思うのですが。 たしかに、テーブルや項目が多ければ大変だとは思いますが、やらなければいけないことならやるしかないと思います。 役に立つか分かりませんが、複数のテーブルの全項目をUNIONで取得するSQLを組み立てるSQLを考えてみました。 --全角スペースでインデントしています select case when COL_NUM = 1 then case when TAB_NUM > 1 then 'UNION ALL' ||CHR(10) end || 'SELECT' || CHR(10) else ',' end || coalesce(P_COLUMN_NAME, 'NULL') || ' AS ' || L_COLUMN_NAME || case when max(COL_NUM) over() = COL_NUM then CHR(10) || 'FROM ' || TABLE_NAME end from ( select TABS.TABLE_NAME , COLS.COLUMN_NAME L_COLUMN_NAME , TAB_COLS.COLUMN_NAME P_COLUMN_NAME , dense_rank() over(order by TABS.TABLE_NAME) TAB_NUM , ROW_NUMBER() over(partition by TABS.TABLE_NAME order by COLS.COLUMN_NAME) COL_NUM from ( select distinct COLUMN_NAME from USER_TAB_COLS where TABLE_NAME in ('Aテーブル', 'Bテーブル') --対象のテーブルを列挙してください ) COLS cross join ( select TABLE_NAME from USER_TABLES where TABLE_NAME in ('Aテーブル', 'Bテーブル') --対象のテーブルを列挙してください ) TABS left join USER_TAB_COLS TAB_COLS on ( TAB_COLS.TABLE_NAME = TABS.TABLE_NAME and TAB_COLS.COLUMN_NAME = COLS.COLUMN_NAME ) ) order by TAB_NUM , COL_NUM ; これを実行すると、たとえば今回提示されているテーブル定義であれば、 SELECT 内容 AS 内容 ,所属 AS 所属 ,日付 AS 日付 ,時間 AS 時間 ,NULL AS 理由 ,社員番号 AS 社員番号 ,結果 AS 結果 FROM Aテーブル UNION ALL SELECT 内容 AS 内容 ,NULL AS 所属 ,日付 AS 日付 ,NULL AS 時間 ,理由 AS 理由 ,社員番号 AS 社員番号 ,NULL AS 結果 FROM Bテーブル というSQLが出来ます。 これをインラインビューにして、SELECTする項目順を入れ替えたり、不要な項目を削除したりすれば少しは楽になるかもしれません。
その他の回答 (2)
- yamada_g
- ベストアンサー率68% (258/374)
すみません。質問をきちんと読めていませんでした・・・ Bテーブルだけに存在する項目もあるのですね。 であれば、AテーブルのSELECT文でNULLを設定すればいいです。 SELECT 社員番号, 日付, 内容, 所属, 時間, 結果, NULL AS 理由 FROM Aテーブル UNION SELECT 社員番号, 日付, 内容, NULL, NULL, NULL, 理由 FROM Bテーブル ORDER BY 社員番号, 内容, 日付; でいかかでしょうか。
- yamada_g
- ベストアンサー率68% (258/374)
存在しない項目にNULLを設定すればUNIONすることができます。 SELECT 社員番号, 日付, 内容, 所属, 時間, 結果 FROM Aテーブル UNION SELECT 社員番号, 日付, 内容, NULL, NULL, NULL FROM Bテーブル ORDER BY 社員番号, 内容, 日付; もし、それぞれのテーブルが社員番号と日付で一意になり、それらのデータは1行にしたいということであれば完全外部結合してもいいと思います。 SELECT NVL(A.社員番号, B.社員番号) AS 社員番号, NVL(A.日付, B.日付) AS 日付, A.内容 AS A内容, B.内容 AS B内容, A.所属, A.時間, A.結果 FROM Aテーブル A FULL OUTER JOIN Bテーブル B ON (A.社員番号 = B.社員番号 AND A.日付 = B.日付) ORDER BY 社員番号, A.内容, B.内容, 日付; みたいな感じです。
お礼
yamada_g 様、ご回答ありがとうございます。 NULLの件ですが、Bテーブルの方も社員番号、日付、内容だけでなく、理由 も出力したいと考えています。 その場合は、NULLでは難しいですよね、、、 また、残念ながら両テーブルは、社員番号と日付では一意にならず、N:Nの 関係となっています。 何もわからず申し訳ありませんが、もう少し教えて頂ければ幸いです。 よろしくお願いします。
お礼
yamada_g様、ご回答ありがとうございます。 返事が遅くなりまして申し訳ありません。 教えて頂いた件、問題なくできました! ちなみに、もしこれらのテーブルが複数存在し、社員番号、日付、内容は キーになるものの、それ以外の項目を、テーブルがある分だけ表示させるような 場合はどのようにするのが良いのでしょうか? 1つ1つNULLを設定するのは難しいかと、、、 よろしくお願いします。