※mahnyさんの回答をより具体的にした補足的内容となっています。
具体的な値でイメージを作ったほうが良いです。
Excelとかでも手書きでも良い。
テーブルA
id | name | B_category | C_category |
---|
| | | |
テーブルB
テーブルC
「テーブルAのB_categoryにはテーブルBのIDが入りC_categoryにはテーブルCのIDが入る」
としましょう。
で、「テーブルAにテーブルBとテーブルCを結合してそれぞれのnameを取る」
というSQLを書こうとしているのが、現在質問されようとしていることになると推測します。
最終形は以下を目指します。
結合結果イメージ
id | name | B_category | B_category_name | C_category | C_category_name |
---|
| | | | | |
それぞれのIDは既にテーブルAが持っているので、nameだけを持ってくる。
nameは別の名前にする。
※手元の環境PostgreSQL13で確認
CREATE TABLE (pgAdmin4で自動生成されたものに少し手を加えたもの)
sql
1CREATE TABLE b
2(
3 id integer NOT NULL,
4 name character varying(20) NOT NULL,
5 CONSTRAINT b_pkey PRIMARY KEY (id)
6);
7CREATE TABLE c
8(
9 id integer NOT NULL,
10 name character varying(20)NOT NULL,
11 CONSTRAINT c_pkey PRIMARY KEY (id)
12);
13
14CREATE TABLE a
15(
16 id integer NOT NULL,
17 name character varying(30) NOT NULL,
18 b_category integer NOT NULL,
19 c_category integer NOT NULL,
20 CONSTRAINT a_pkey PRIMARY KEY (id),
21 CONSTRAINT fk_b_category FOREIGN KEY (b_category)
22 REFERENCES b (id) MATCH SIMPLE
23 ON UPDATE NO ACTION
24 ON DELETE NO ACTION,
25 CONSTRAINT fk_c_category FOREIGN KEY (c_category)
26 REFERENCES c (id) MATCH SIMPLE
27 ON UPDATE NO ACTION
28 ON DELETE NO ACTION
29);
30
外部キー制約を入れている関係でデータはb,cから入れてください。
SQL
1insert into b values (1,'B1');
2insert into b values (2,'B2');
3insert into b values (3,'B3');
4insert into b values (4,'B4');
5insert into b values (5,'B5');
6
7insert into c values (1,'C1');
8insert into c values (2,'C2');
9insert into c values (3,'C3');
10insert into c values (4,'C4');
11insert into c values (5,'C5');
12
13insert into A values (1,'hoge1',1,1);
14insert into A values (2,'hoge2',3,4);
15insert into A values (3,'hoge3',5,2);
16
質問に提示されているSQL
sql
1select
2 *
3from a
4 join b on b.id = a.b_category
5 join c on c.id = a.c_category
※joinはinner joinと同義
※A5:SQL Mk-2 2.15.3による結果
DBによってはここでエラーが出ます。
なぜならa,b,cにid,nameという同名のカラムがあるからです。
*は対象のテーブル全てを取得してくるのでそのようになります。
DBやツールによっては、提示のようにjoinされたカラムに連番つけてくれて回避してくれます。
pgAdmin4ではこう。
同名で出ていますが、内部的には重複しないように変換がかかっている可能性があります。
「それぞれのテーブルの」を取得したい場合は
テーブル名.カラム名
です。
sql
1select
2 a.*
3 ,b.*
4 ,c.*
5from a
6 join b on b.id = a.b_category
7 join c on c.id = a.c_category
これでも結果は変わりません。
id,nameをそのまま持ってきています。
「結合結果イメージ」ではbとcのidは不要ですね。
テーブル名.カラム名
の法則にのっとり、「全て」を表す*
ではなく、カラム名を明示します。
sql
1select
2 a.id
3 ,a.name
4 ,a.b_category
5 ,a.c_category
6 ,b.name
7 ,c.name
8from a
9 join b on b.id = a.b_category
10 join c on c.id = a.c_category
また、「カラム名」「テーブル名」には「エイリアス」と言って、別名をつけることができます。
今回のようにnameという名称が重複していたり、テーブル名カラム名が長い時に短縮名称をつけて使いまわすようなときに使えます。
※詳しくは「使いたいDB エイリアス」で調べてください。
最終形
sql
1select
2 a.id
3 ,a.name
4 ,a.b_category
5 ,b.name b_category_name
6 ,a.c_category
7 ,c.name c_category_name
8from a
9 join b on b.id = a.b_category
10 join c on c.id = a.c_category
ざっくり言ってしまうと「テーブル結合」は「大きい1つのテーブルを作る」ようなものです。
なので「inner join限定」であればこんな感じにも書けます。(出力結果は同じ)
sql
1select
2 a.id
3 ,a.name
4 ,a.b_category
5 ,b.name b_category_name
6 ,a.c_category
7 ,c.name c_category_name
8from a,b,c
9 where b.id = a.b_category
10 and c.id = a.c_category