koheitakahashiのブログ

2020.07.01にプログラマーとして生を受けた私が学んだことや、日常について徒然に書いていきます。

相関サブクエリの使い方

サブクエリとは?

使い捨てのビューのことです。ビューとは、自分が頻繁に使うようなSELECT文をデータベースに登録しておく機能のことを言います。

相関サブクエリとは?

例えば、以下のようなデータベースがあるとします。

CREATE TABLE Customer
( id        CHAR(4)       NOT NULL,
  name      VARCHAR(100)  NOT NULL,
  address    VARCHAR(100)  NOT NULL,
  sex       VARCHAR(3)    NOT NULL,
  age       INTEGER       ,
  torokubi  DATE       ,
  PRIMARY KEY (id));

BEGIN TRANSACTION;

INSERT INTO Customer VALUES ('0001','深沢諭吉', '東京都', '男性', '35', '2001-08-06');
INSERT INTO Customer VALUES ('0002','北口英世', '静岡県', '男性', '24', '2001-11-11');
INSERT INTO Customer VALUES ('0003','樋口二葉', '東京都', '女性', '42', '2002-02-24');
INSERT INTO Customer VALUES ('0004','天沢栄一', '静岡県', '男性', '16', '2002-04-16');
INSERT INTO Customer VALUES ('0005','津田桃子', '東京都', '女性', '56', '2003-05-22');
INSERT INTO Customer VALUES ('0006','南里柴三郎', '静岡県', '男性', '80', '2004-12-01');

COMMIT;

ここで、「県別の平均年齢よりも高い年齢の顧客の名前をピックアップした」という状況になったとき、さっきのサブクエリを使うと実現できるかもしれません。

やってみましょう。

1. まず、県別の年齢の平均を出してみる

コード1

SELECT AVG(age), address
  FROM Customer 
  GROUP BY address;

結果1

         avg         | address 
---------------------+---------
 40.0000000000000000 | 静岡県
 44.3333333333333333 | 東京都
(2 rows)

2. 1のSELECT文をそのままWHERE句に入れる

コード2

SELECT name, age, address
FROM Customer
WHERE age > (SELECT AVG(age)
            FROM Customer 
            GROUP BY address);

これで、うまくいくはず・・・

結果2

ERROR:  more than one row returned by a subquery used as an expression

あれ、エラーが起きた😱

エラーの原因は?

実は、サブクエリをWHERE句の中に記述するためには、サブクエリが返す値が1つでなくてはなりません。このように、返す値が1つという条件を持ったサブクエリをスカラ・サブクエリと言います。

今回は、サブクエリ部分が東京都と静岡県の2つの平均年齢を返したため、このようなエラーが出てしまいました。

ではどうすればいいのでしょう?

ここで相関サブクエリが登場

実はコード2に1文だけ加えれば上記の課題が解決できるのです。

それがWHERE句です。

コード3

SELECT name, age, address
FROM Customer AS C1
WHERE age > (SELECT AVG(age)
            FROM Customer AS C2
            WHERE C1.address = C2.address
            GROUP BY address);

このようにWHERE句を加えると、

結果3

    name    | age | address 
------------+-----+---------
 津田桃子   |  56 | 東京都
 南里柴三郎 |  80 | 静岡県
(2 rows)

このように望んだ結果が返ってきました。 これが相関サブクエリです💪

参考文献

ミック著 2016 『SQL ゼロから始めるデータベース 第2版』 翔泳社