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

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

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

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Q&A

解決済

3回答

3316閲覧

外部結合で結合できないデータも取りたいです

erohermit

総合スコア7

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

0グッド

0クリップ

投稿2018/06/06 07:42

編集2018/06/06 08:13

前提・実現したいこと

初めまして、SQL初心者です。

早速ですが、
A(グループ),B(生徒),C(性別)というテーブルがあるとします。

AとBは1:Nの関係で、
BとCは1:1の関係です。

  • A(グループ)テーブル
id(pk)b_id(pk)
11
12
13
24
35
  • B(生徒)テーブル
id(pk)c_id
11
21
32
41
51
  • C(性別)テーブル
id(pk)sex
1men
2women

発生している問題・エラーメッセージ

上記のテーブル構成で、グループに存在しない性別の生徒も含めて全レコードを取得したいのですが、SQL一回で取得できるものなのでしょうか。

  • 期待する結果
a_idb_idc_idname
111men
121men
132women
241men
2null2women
351men
3null2women

試したこと

-- Aテーブル作成 create table A (id integer, b_id integer); insert into A values (1,1); insert into A values (1,2); insert into A values (1,3); insert into A values (2,4); insert into A values (3,5); -- Bテーブル作成 create table B (id integer, c_id integer); insert into B values (1,1); insert into B values (2,1); insert into B values (3,2); insert into B values (4,1); insert into B values (5,1); -- Cテーブル作成 create table C (id integer, name varchar(10)); insert into C values (1, 'men'); insert into C values (2, 'women');

外部結合なら結合できなかったものも取れるということでしたので、試して見ましたが
取得できませんでした・・

select A.id a_id, B.id b_id, C.id c_id, C.name from A inner join B on A.b_id = B.id right outer join C on C.id = B.c_id order by A.id,C.id; +------+------+------+-------+ | a_id | b_id | c_id | name | +------+------+------+-------+ | 1 | 1 | 1 | men | | 1 | 2 | 1 | men | | 1 | 3 | 2 | women | | 2 | 5 | 1 | men | | 2 | 4 | 1 | men | +------+------+------+-------+

補足情報(FW/ツールのバージョンなど)

mysql 5.7を使用しております。

ご教授のほどよろしくお願い致します。

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

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

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

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

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

Orlofsky

2018/06/06 07:56

SQLで使われるテーブルはCREATE TABLEされている必要があります。テーブル定義の説明もCREATE TABLEで載せると適切なコメントが付き易いです。同じようにSELECTされるデータもINSERTされている必要がありますから、INSERT文で載せておくとコメントが付き易いです。
erohermit

2018/06/06 08:05

コメントありがとうございます。失礼しました。create文、insert文を載せて起きました。
m.ts10806

2018/06/06 08:10

質問編集画面タイトル横にある「初心者アイコン」をご活用ください。「初心者」と質問で書くよりも伝わりますし、質問一覧に表示されるのでわかりやすくなります。
erohermit

2018/06/06 08:22

教えていただき、ありがとうございます。活用します
guest

回答3

0

テーブル構造が微妙な気がします。
AとBが1:Nの関係ならば、BテーブルにグループID列を定義すべきです。
あと、BとCは1:1という説明がありますが、N:1な気がします。

投稿2018/06/06 08:07

sagami1991

総合スコア216

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

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

0

ベストアンサー

生徒を優先したいならBからAに外部結合する必要があります
但し、Aが取得できない場合は当然A.idはnullになります。
ですので、並び順も工夫が必要です。

SQL

1select A.id a_id, B.id b_id, C.id c_id, C.name 2from B left join A 3 on A.b_id = B.id 4 left outer join C 5 on C.id = B.c_id 6order by coalesce(A.id, b.id), C.id

※サンプルデータだと5件にしかならないので、差分の2行は何がしたいのかな?

a_idb_idc_idname
111men
121men
132women
241men
351men

追記

aとcの直積(full join)をグループidと性別でグルーピングしたものを基準に、
aとbを結合したものに外部結合します。

SQL

1select ac.a_id, ab.b_id, ac.c_id, ac.name 2from ( 3 select a.id as a_id, c.id as c_id, c.name 4 from a, c 5 group by a.id, c.id, c.name 6 ) ac left join ( 7 select a.id as a_id, a.b_id, b.c_id 8 from A inner join b 9 on a.b_id=b.id 10 ) ab 11 on ac.a_id=ab.a_id and ac.c_id=ab.c_id 12order by ac.A_id, ab.b_id, ac.c_id 13

ポイントになるのは、基準となるものを如何に作り出すかと言う事ですね。
後はその基準に一度に結合する条件を揃える整形をしたものと結合する。

投稿2018/06/06 07:58

編集2018/06/06 09:33
sazi

総合スコア25195

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

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

erohermit

2018/06/06 08:09

回答ありがとうございます。 > Aが取得できない場合は当然A.idはnull やっぱりこれは、どうしようもできないものでしょうか・・
sazi

2018/06/06 08:10

どうしたいんですか?ルールが有るなら作り出すことも可能ではありますが。
erohermit

2018/06/06 08:21

各グループに男女が存在するしないをリストで取りたいと思っています。 saziさんの結果の表で、a.idがnullのところにそれぞれ、2と3が入ったリストが取れると良いのです。
sazi

2018/06/06 08:37 編集

追記しました。あ、駄目か、ちょっと修正します。
sazi

2018/06/06 09:11

修正しました。ちょっと面倒ですね。
erohermit

2018/06/06 09:31

追記確認致しました。 期待する結果が取得できることを確認できました! > 基準となるものを如何に作り出すかと言う事 大変勉強になります。 full joinに関してもまだまだ知識がないのでいろいろ調べてみようかと思います! ありがとうございました。 今後ともよろしくお願いします。
guest

0

単純な SQL では無理ですね。
問題は「存在しない性別の生徒のデータをでっち上げる」ことにあるのですが、外部結合で導き出せる類いのものではありません。
やりたいことを順に考えると、

  1. あるグループに所属する生徒の一覧を、「男女別に」取り出す(この結果を t1, t2 とする)
  2. count(t1) = 0 の場合、b.id = null かつ c.id = 1 になるレコードをでっちあげ、t1 の変わりとする。count(t2) = 0 の場合も同様(c.id=2)
  3. t1 と t2 を union する

といった処理をする必要がありそうです。
一つの SQL で書けないわけではないのですが、変に複雑にするよりはロジックで対処した方がよいように思います。

投稿2018/06/06 08:31

tacsheaven

総合スコア13703

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

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

erohermit

2018/06/06 10:17

コメントありがとうございます。 時にはロジックで対処した方が良い場合もあるということですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問