teratail header banner
teratail header banner
質問するログイン新規登録

質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.30%
SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

2回答

2357閲覧

片方のテーブルにデータが存在しない場合の、JOIN方法

revoiot

総合スコア188

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2022/02/12 00:39

0

0

データベース初心者です。

ヘルスケアマスタ、会員マスタと、ユーザーマスタ(ID情報を一元管理したもの)で結合させて、下記アウトプットビューにあるように、日付および個人データ(会員番号等)ごとに、ヘルスケアマスタと会員マスタのデータ(歩数、作業時間等)を出力させたいです。

アウトプットビューに出力する際の条件として、ヘルスケアマスタと会員マスタで一致する日付データが存在しなくても、ヘルスケアマスタと会員マスタから抽出してきたカラム部分についてはデータがない片側はnullでよいので出力させたく、ユーザーマスタから抽出してきたカラム部分については、nullではなく、対象のレコードに関わる個人データをかならず表示させるようにしたいです。
下記の表のようなイメージです。

ユーザーマスタカラムヘルスケアカラム会員カラム
ヘルスケアマスタ、会員カラムでどちらかが欠けているレコードがあっても、nullではなく個人データを出力データがなければnullでokデータがなければnullでok

下記のSQL文のように、それぞれのマスタをfull outer joinで二重に結合させ、ヘルスケアか会員マスタのどちらかでデータがなくても出力させるようにOR文で条件指定しましたが、②のアウトプットビューにあるように、ユーザーマスタから抽出してきたカラム部分が nullになってしまうようです。

ヘルスケアか会員マスタのどちらかでデータがなくても、ユーザーマスタから抽出してきたカラム部分については、必ず出力させるようにするためには、下記SQL文をどのように修正が必要でしょうか?
ご存じの方いましたら、ご教示いただけると幸いです。

SELECT * FROM (("ヘルスケアマスタ" FULL OUTER JOIN "会員マスタ ON "ヘルスケアマスタ"."スマートウオッチ測定日" = "会員マスタ"."日") FULL OUTER JOIN "ユーザーマスタ" ON "ヘルスケアマスタ"."スマートウオッチID" = "ユーザーマスタ"."会員番号" OR "会員マスタ"."会員番号" = "ユーザーマスタ"."会員番号")

①正解アウトプット用ビュー

スマートウオッチID会員番号ユーザ名スマートウオッチ測定日歩数睡眠時間作業日作業時間
5700000dummy0001田中太郎2022-12-06100009.7nullnull
5700023dummy0002佐藤一郎2022-12-0770005.6nullnull
5700056dummy0003山田花子2022-12-0812007.0nullnull
5700000dummy0001田中太郎nullnullnull2022-01-099.0
5700023dummy0002佐藤一郎nullnullnull2022-01-1012.0
5700056dummy0003山田花子nullnullnull2022-01-1111.0
5700000dummy0001田中太郎2022-01-12150008.02022-01-128.0

②ユーザーマスタのカラムが nullになってしまう現在のアウトプット用ビュー

スマートウオッチID会員番号ユーザ名スマートウオッチ測定日歩数睡眠時間作業日作業時間
5700000null田中太郎2022-12-06100009.7nullnull
5700023null佐藤一郎2022-12-0770005.6nullnull
5700056null山田花子2022-12-0812007.0nullnull
nullnullnullnullnullnull2022-01-099.0
nullnullnullnullnullnull2022-01-1012.0
nullnullnullnullnullnull2022-01-1111.0
5700000dummy0001田中太郎2022-01-12150008.02022-01-128.0

----------------------------------------------------
↓下記はマスタ一覧です。

ヘルスケアマスタ

スマートウオッチ測定日スマートウオッチID歩数睡眠時間
2022-12-065700000100009.7
2022-12-07570002370005.6
2022-12-08570005612007.0
2022-01-125700000150008.0

会員マスタ

作業日会員番号作業時間
2022-01-09dummy00019.0
2022-01-10dummy000212.0
2022-01-11dummy000311.0
2022-01-12dummy00018.0

ユーザマスタ

スマートウオッチID会員番号ユーザ名
5700000dummy0001田中太郎
5700023dummy0002佐藤一郎
5700056dummy0003山田花子

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2022/02/12 00:51

アイデアレベルなのでこちらに書きますが、まずユーザーマスタから始めてJOINさせてみたらどうなりますか?
revoiot

2022/02/12 07:34

maisumakunさんのご指摘の通り、 下記のSQL文のように、ユーザーからjoinした場合、ユーザーマスタから抽出してきたカラム部分が nullになってしまう現象は変わらないようです。今回データがない片方はnullとして出力させたいので、Full outer joinとして結合しています。 SELECT * FROM (("ユーザマスタ" FULL OUTER JOIN "ヘルスケアマスタ" ON "ヘルスケアマスタ"."スマートウオッチID" = "ユーザマスタ"."スマートウオッチID") FULL OUTER JOIN "会員マスタ" ON "ヘルスケアマスタ"."スマートウオッチ測定日" = "会員マスタ"."作業日")
guest

回答2

0

ベストアンサー

PK情報や実際の仕様などがわからないため、工夫次第ではもう少し単純化できそうですが、たとえば以下のようなクエリはどうでしょうか?

sql

1WITH 2A AS ( 3 SELECT U.スマートウオッチID, U.会員番号, U.ユーザ名, H.スマートウオッチ測定日, H.歩数, H.睡眠時間 4 FROM ユーザマスタ U 5 JOIN ヘルスケアマスタ H ON U.スマートウオッチID = H.スマートウオッチID 6), 7B AS ( 8 SELECT U.スマートウオッチID, U.会員番号, U.ユーザ名, K.作業日, K.作業時間 9 FROM ユーザマスタ U 10 JOIN 会員マスタ K ON U.会員番号 = K.会員番号 11) 12SELECT S.スマートウオッチID, S.会員番号, S.ユーザ名, A.スマートウオッチ測定日, A.歩数, A.睡眠時間, B.作業日, B.作業時間 13FROM ( 14 SELECT A.スマートウオッチID, A.会員番号, A.ユーザ名, A.スマートウオッチ測定日 FROM A 15 UNION 16 SELECT B.スマートウオッチID, B.会員番号, B.ユーザ名, B.作業日 FROM B 17) AS S (スマートウオッチID, 会員番号, ユーザ名, 基準日) 18LEFT OUTER JOIN A ON S.スマートウオッチID = A.スマートウオッチID AND S.会員番号 = A.会員番号 AND S.ユーザ名 = A.ユーザ名 AND S.基準日 = A.スマートウオッチ測定日 19LEFT OUTER JOIN B ON S.スマートウオッチID = B.スマートウオッチID AND S.会員番号 = B.会員番号 AND S.ユーザ名 = B.ユーザ名 AND S.基準日 = B.作業日

投稿2022/02/12 14:50

neko_the_shadow

総合スコア2395

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

アウトプット用ビューを作るときに、
どっちのテーブルにあるデータを使っていますか?
データが存在しない方のテーブルのデータを参照するとnullですよね。

mysql8だと
COALESCE
postgresql13だと
COALESCE
が使えそうです。
引数に与えるデータのうち、NULLではない最初のものが使われるので、
テーブルAにもBにも存在するデータで基本的に同じってことであれば、
COALESCE(テーブルA.名前, テーブルB.名前) AS "名前"みたいにするとよいです。

と書いてから気づきましたが、
maisumakunさんの指摘にあるように、
(ユーザマスタ LEFT JOIN ヘルスケアマスタ) LEFT JOIN 会員マスタ
っていうJOINの仕方をすれば、ナナシさんにはならないはずですよね。

投稿2022/02/12 00:52

編集2022/02/12 00:58
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

revoiot

2022/02/12 07:31 編集

回答ありがとうございます! COALESCEというもの初めて知りました。 今回ヘルスケアマスタと会員マスタでは、別々のID情報で管理されているのですが、早速、COALESCE("ヘルスケアマスタ"."スマートウオッチID" , "会員マスタ"."会員番号")で出力してみたところ、1つの列に異なるID情報を集約させることができました。しかし、スマートウオッチIDと会員番号では、全く種類が異なるものであり、できれば、それぞれのID情報を別々に列を出力させたいです。 ユーザーマスタに全てのマスタのID情報を持たせているので、その情報をうまく参照して、 ヘルスケアマスタと会員マスタのユーザーマスタのID情報を出力させることは可能だったりするのでしょうか? maisumakunさんのご指摘の通り、 下記のSQl文のように、ユーザーからjoinした場合、ユーザーマスタから抽出してきたカラム部分が nullになってしまう現象は変わらないようです。今回データがない片方はnullとして出力させたいので、Full outer joinとして結合しています。 SELECT * FROM (("ユーザマスタ" FULL OUTER JOIN "ヘルスケアマスタ" ON "ヘルスケアマスタ"."スマートウオッチID" = "ユーザマスタ"."スマートウオッチID") FULL OUTER JOIN "会員マスタ" ON "ヘルスケアマスタ"."スマートウオッチ測定日" = "会員マスタ"."作業日")
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問