
初歩的なSQLの質問で申し訳ありません。
以前にも同じような内容で投稿させて頂きましたが、教えて下さい。
下記のような、ある異なる名前の同項目を持つ2つのテーブルが存在します。
《テーブル》
Aテーブル
社員番号、日付、内容、所属、時間、結果
Bテーブル
社員番号、日付、内容、理由
※ 内容に関しては、AテーブルとBテーブルで全く違います。
これらの2つのテーブルをマージさせ、社員番号毎の内容毎、日付順に
したいと考えています。
以前に以下のようなUNIONを教えてもらいましたが、所属、時間、結果、理由という
項目全てを出力するとした場合、どのように記載すれば良いでしょうか?
UNIONの場合、項目が異なるとエラーとなってしまうかと、、、
《UNIONのSQL》
SELECT *
FROM (
SELECT 社員番号, 日付, 内容
FROM Aテーブル
UNION
SELECT 社員番号, 日付, 内容
FROM Bテーブル
)
ORDER BY 日付, 社員番号, 内容
教えて下さい。
よろしくお願いします。
No.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する項目順を入れ替えたり、不要な項目を削除したりすれば少しは楽になるかもしれません。
No.2
- 回答日時:
すみません。
質問をきちんと読めていませんでした・・・Bテーブルだけに存在する項目もあるのですね。
であれば、AテーブルのSELECT文でNULLを設定すればいいです。
SELECT 社員番号, 日付, 内容, 所属, 時間, 結果, NULL AS 理由
FROM Aテーブル
UNION
SELECT 社員番号, 日付, 内容, NULL, NULL, NULL, 理由
FROM Bテーブル
ORDER BY 社員番号, 内容, 日付;
でいかかでしょうか。
yamada_g様、ご回答ありがとうございます。
返事が遅くなりまして申し訳ありません。
教えて頂いた件、問題なくできました!
ちなみに、もしこれらのテーブルが複数存在し、社員番号、日付、内容は
キーになるものの、それ以外の項目を、テーブルがある分だけ表示させるような
場合はどのようにするのが良いのでしょうか?
1つ1つNULLを設定するのは難しいかと、、、
よろしくお願いします。
No.1
- 回答日時:
存在しない項目に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の
関係となっています。
何もわからず申し訳ありませんが、もう少し教えて頂ければ幸いです。
よろしくお願いします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
「マスタ」と「テーブル」の違...
-
重複するキーから一番古い年月...
-
PLSQLで集計関数の値を配列に入...
-
続.ORACLEのSELECTのソートに...
-
Accessユニオンクエリーで2つ...
-
Accessでフィールドを比較した...
-
主キーの変更
-
PLSQLの識別子エラー
-
履歴を管理するテーブル構造に...
-
2つのテーブルから条件に一致...
-
行方向のデータを横に並べる
-
VIEWでテーブルの集計結果...
-
3つ以上のテーブルをUNIONする...
-
seoについておしえてください
-
ACCESS2007 フォーム 「バリア...
-
オラクルではできるのにSQLSERV...
-
エクスポート時の改行コードに...
-
Access 削除クエリが重い
-
SELECT時の行ロックの必要性に...
-
SELECT文でのデッドロックに対...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
「マスタ」と「テーブル」の違...
-
2つのテーブルから条件に一致...
-
重複するキーから一番古い年月...
-
主キーの変更
-
update文で質問です。 下記の条...
-
ACCESS 一つのフィールドに複...
-
続.ORACLEのSELECTのソートに...
-
accessで移動平均する方法
-
行方向のデータを横に並べる
-
Accessでフィールドを比較した...
-
PLSQLの識別子エラー
-
商品コード番号を入力すると商...
-
ACCESSのデータシート形式のフ...
-
複数InnerJoin時の処理落ち回避法
-
Accessのテーブル設計について...
-
正規化・リレーションシップに...
-
Accessのコンボボックスの使い...
-
データベースの問題
-
ACCESSのコンパイルエラーについて
-
SQL結合条件
おすすめ情報