子育てエンジニアブログ

子育てに励むシステムエンジニア(SE)のブログ

【SQL】【SQL Server】SELECTステートメントにサブクエリ(副問合せ)を書く

SELECTステートメントにサブクエリを書く。
今までサブクエリはFROM句やWHERE句には使ってたけど、SELECTにも書けることを知ったのでメモ。
ていうかどういう動きになるのかよくわからなかったので検証。

DBは今回はSQL Serverです。

早速SQLですが今回は下記のような場合。

CREATE TABLE #work1
(id int
 ,name varchar(10)
);

CREATE TABLE #work2
(id int
 ,name varchar(10)
);

INSERT INTO #work1
    ([id], [name])
VALUES
    (1, 'test1');

INSERT INTO #work2
    ([id], [name])
VALUES
    (2, 'test2');

select #work1.id ,(select id from #work2) from #work1

実行結果
f:id:STSA:20201113225227p:plain

2つのテーブルはどちらも1レコードのみなのでわかりやすい。

では、次のようなにどちらも複数レコードある時はどうだろう。

CREATE TABLE #work1
(id int
 ,name varchar(10)
);

CREATE TABLE #work2
(id int
 ,name varchar(10)
);

INSERT INTO #work1
    ([id], [name])
VALUES
    (1, 'test1');
    
INSERT INTO #work1
    ([id], [name])
VALUES
    (11, 'test11');
    
INSERT INTO #work2
    ([id], [name])
VALUES
    (2, 'test2');
    
INSERT INTO #work2
    ([id], [name])
VALUES
    (22, 'test22');

select #work1.id ,(select id from #work2) from #work1


実行結果
f:id:STSA:20201113225318p:plain

エラーになる。
そうだよね。だって1つに絞れないもん。

では、次のように1つに絞れるような場合はどうだろう。

select #work1.id ,(select id from #work2 where id = 2) from #work1

実行結果
f:id:STSA:20201113225351p:plain

これはいけるね。けど、これだとidは2しか表示されない。

じゃあ、ちょっとデータを変えて、work1とwork2でidで紐付けされるようにする。
で、いつものようにidを条件にする。

CREATE TABLE #work1
(id int
 ,name varchar(10)
);

CREATE TABLE #work2
(id int
 ,name varchar(10)
);

INSERT INTO #work1
    ([id], [name])
VALUES
    (1, 'test1');
    
INSERT INTO #work1
    ([id], [name])
VALUES
    (2, 'test11');
    
INSERT INTO #work2
    ([id], [name])
VALUES
    (1, 'test2');
    
INSERT INTO #work2
    ([id], [name])
VALUES
    (2, 'test22');

select #work1.id ,(select id from #work2 where id = #work1.id) from #work1

実行結果
f:id:STSA:20201113225428p:plain

これは思い通り。
ただ、SELECT句に書くメリットって何があるだろう。


【SQL】【SQL Server】紐付かないテーブル同士で片方がデータがなくても抽出する方法

紐付かないテーブル同士で片方がデータがなくても抽出する方法についてです。
どんなタイミングでそういうことをしたくなるのか、なかなかタイミングはないとは思うけどちょっと詰まったのでメモ。

例えば、work1というテーブルがあってこちらは0〜複数レコードが入る。
そしてwork2というテーブルには1レコードだけ確実にある状態。
で、work1の内容とwork2の内容を合わせて抽出したい。(この2つのテーブルに紐付けられる情報はない。)
また、work1が0件だったとしても、work2の1レコードの内容は表示したい。

何がやっかいかというと、テーブル間に紐付けがないというところと、
メインとなるテーブルが0〜複数件なのでこちらをFROM句に書くと何も抽出できない。

んー、紐付けられたら外部結合で簡単なんだけどね。。
今回はSQL Serverで実現。

結果、T-SQLでレコードの存在チェックで条件分岐させ、別々のSQLを実行させることにした。

早速SQLについて。

1.複数件データがある時。

CREATE TABLE #work1
(id int
 ,name varchar(10)
);

CREATE TABLE #work2
(name2 varchar(10)
);

INSERT INTO #work1
    ([id], [name])
VALUES
    (1, 'test1');
    
INSERT INTO #work1
    ([id], [name])
VALUES
    (2, 'test11');

INSERT INTO #work2
    ([name2])
VALUES
    ('test2');
    
IF (EXISTS(SELECT 1 FROM #work1))
BEGIN 
  select id,name,(select name2 from #work2) from #work1
END
ELSE
BEGIN
    select '',name2 from #work2
END

f:id:STSA:20201113230209p:plain

2.片方がデータが0件の時。

CREATE TABLE #work1
(id int
 ,name varchar(10)
);

CREATE TABLE #work2
(name2 varchar(10)
);

INSERT INTO #work2
    ([name2])
VALUES
    ('test2');
    
IF (EXISTS(SELECT 1 FROM #work1))
BEGIN 
  select id,name,(select name2 from #work2) from #work1
END
ELSE
BEGIN
    select '',name2 from #work2
END

f:id:STSA:20201113230353p:plain

やりたいことは実現できたけど、単一のSQLで実現する方法はないものか。