Python | DB・SQL:SELECT

Python
スポンサーリンク

概要(SELECT は「欲しいデータだけを取り出すコマンド」)

SQL の SELECT 文は、データベースから「欲しいデータだけ」を取り出すためのコマンドです。
Excel の表から「この列だけ見たい」「20 歳以上だけ見たい」「若い順に並べたい」といった操作を、
言葉(SQL)でデータベースにお願いするイメージです。

SELECT をちゃんと理解すると、
「どんなデータが、どんな条件で、どんな順番で欲しいか」を自由に指定できるようになります。
Django の ORM も、裏側ではほぼ同じことを SQL でやっているので、
SELECT の感覚があると Django のクエリも一気に理解しやすくなります。

ここから、SELECT の基本形から少しずつ深掘りしていきます。


SELECT の基本形をまず覚える

一番シンプルな形

まずは、超基本形です。

SELECT 列1, 列2
FROM テーブル名;
SQL

例えば、users テーブルがあるとします。

users テーブル

id | name   | age | email
---+--------+-----+--------------------
 1 | Taro   | 25  | taro@example.com
 2 | Hanako | 30  | hanako@example.com
 3 | Ken    | 19  | ken@example.com

このとき、全員の name と age だけを取り出したいなら、こう書きます。

SELECT name, age
FROM users;
SQL

結果はこんな感じです。

name   | age
-------+----
Taro   | 25
Hanako | 30
Ken    | 19

「どの列が欲しいか」を SELECT の後ろに並べる、
「どのテーブルから取るか」を FROM の後ろに書く、
この二つが SELECT の最小単位です。

すべての列が欲しいときの「*」

テーブルの全列を取りたいときは、* を使います。

SELECT *
FROM users;
SQL

これは「users テーブルの全列・全行をそのまま見せて」とお願いしている形です。
練習のときや、テーブルの中身をざっと確認したいときには便利ですが、
実務では「本当に全部必要か?」を考えて、
必要な列だけ指定する癖をつけると良いです。


WHERE で「欲しい行だけ」に絞り込む

条件を付けないと「全部」取れてしまう

SELECT は、WHERE を書かないと「全行」が対象になります。
users テーブルが 100 万件あっても、WHERE がなければ 100 万件全部返ってきます。

だからこそ、
「どの行が欲しいのか」を WHERE でしっかり指定するのがとても重要です。

基本形はこうです。

SELECT 列1, 列2
FROM テーブル名
WHERE 条件;
SQL

例えば、20 歳以上のユーザーだけ欲しいならこうです。

SELECT name, age
FROM users
WHERE age >= 20;
SQL

結果はこうなります。

name   | age
-------+----
Taro   | 25
Hanako | 30

Ken は 19 歳なので、条件に合わず除外されます。

文字列の条件と等号

メールアドレスが特定のもののユーザーだけ取りたいなら、こうです。

SELECT *
FROM users
WHERE email = 'taro@example.com';
SQL

文字列はシングルクォート '...' で囲みます。
ここでのポイントは、「= は完全一致」ということです。
部分一致(「example.com を含む」など)は、後で出てくる LIKE を使います。

複数条件を AND / OR で組み合わせる

例えば、「20 歳以上かつ 30 歳以下」のユーザーだけ欲しいなら、こうです。

SELECT name, age
FROM users
WHERE age >= 20 AND age <= 30;
SQL

「20 歳未満または 30 歳より上」のユーザーなら、OR を使います。

SELECT name, age
FROM users
WHERE age < 20 OR age > 30;
SQL

AND は「両方満たす」、OR は「どちらかを満たす」です。
条件が複雑になってきたら、括弧でグループ化することもできます。

WHERE (age >= 20 AND age <= 30) OR email LIKE '%example.com'
SQL

WHERE は SELECT の「心臓部」です。
どの行を対象にするかを、ここでしっかりコントロールします。


ORDER BY で並び順をコントロールする

昇順(ASC)と降順(DESC)

ORDER BY は「並び替え」です。
年齢の若い順に並べたいなら、こうです。

SELECT name, age
FROM users
ORDER BY age ASC;
SQL

ASC は昇順(小さい順)です。
年齢の高い順にしたいなら、DESC(降順)を使います。

SELECT name, age
FROM users
ORDER BY age DESC;
SQL

ORDER BY は、WHERE の後ろに書きます。

SELECT name, age
FROM users
WHERE age >= 20
ORDER BY age DESC;
SQL

このように、「まず条件で絞り込み、そのあと並び替える」という流れになります。

複数列で並び替える

例えば、「年齢の高い順、同じ年齢なら名前の昇順」という並びにしたい場合は、こうです。

SELECT name, age
FROM users
ORDER BY age DESC, name ASC;
SQL

ORDER BY age DESC, name ASC
のように、カンマで複数の列を指定できます。

ORDER BY を使いこなせると、
「見たい順番でデータを眺める」ことができるようになります。


LIMIT で「何件まで」に制限する

上位 N 件だけ欲しいとき

データが大量にあるとき、
「とりあえず上から 10 件だけ見たい」ということがよくあります。
そのときに使うのが LIMIT です。

SELECT name, age
FROM users
ORDER BY age DESC
LIMIT 10;
SQL

これで、「年齢の高い順に並べた上位 10 人」だけが返ってきます。

ORDER BY と組み合わせるのが定番です。
ORDER BY がない状態で LIMIT すると、
「どの 10 件か」が不定になることが多いので注意です。

ページング(OFFSET と組み合わせる)

少し進んだ話ですが、
「11〜20 件目だけ欲しい」といったときは OFFSET を使います。

SELECT name, age
FROM users
ORDER BY age DESC
LIMIT 10 OFFSET 10;
SQL

これは、「10 件スキップして、次の 10 件を取る」という意味です。
Web アプリのページング(2 ページ目、3 ページ目…)は、
この LIMIT と OFFSET を組み合わせて実現されることが多いです。


DISTINCT で重複を消す

「ユニークな値だけ」が欲しいとき

例えば、users テーブルに「同じドメインのメールアドレス」がたくさんあるとします。
メールアドレスのドメインだけを取り出して、
重複を除いた一覧が欲しいときに使うのが DISTINCT です。

SELECT DISTINCT email
FROM users;
SQL

これは、「email 列の値を重複なしで取り出す」という意味です。

複数列に対して DISTINCT を使うこともできます。

SELECT DISTINCT name, age
FROM users;
SQL

この場合、「name と age の組み合わせ」が重複しないようにまとめられます。

DISTINCT は便利ですが、
データ量が多いと重くなりがちなので、
「本当に必要なときだけ使う」という意識も大事です。


集計と GROUP BY の入口だけ触れておく

COUNT, SUM, AVG などの集計関数

SELECT では、「行をそのまま返す」だけでなく、
集計結果を返すこともできます。

例えば、ユーザーが何人いるかを数えるには、COUNT を使います。

SELECT COUNT(*) AS user_count
FROM users;
SQL

結果は 1 行 1 列になります。

user_count
----------
3

年齢の平均を出したいなら、AVG を使います。

SELECT AVG(age) AS avg_age
FROM users;
SQL

合計を出す SUM、最大値の MAX、最小値の MIN などもあります。

SELECT
  SUM(age) AS sum_age,
  MAX(age) AS max_age,
  MIN(age) AS min_age
FROM users;
SQL

GROUP BY で「グループごと」に集計する

例えば、「年齢ごとに何人いるか」を知りたいとします。
このときに使うのが GROUP BY です。

SELECT age, COUNT(*) AS count
FROM users
GROUP BY age;
SQL

結果はこうなります。

age | count
----+------
19  | 1
25  | 1
30  | 1

「subject ごとの合計勉強時間」など、
Django でよくやる集計処理の多くは、
裏側でこの GROUP BY と集計関数が使われています。

ここは少し難しめなので、
最初は「COUNT や SUM がある」「GROUP BY でグループごとに集計できる」
くらいのイメージだけ持っておけば十分です。


実務的に大事な SELECT の「考え方」

いきなり複雑に書かないで、「段階的に」絞る

初心者がやりがちなのは、
いきなり 1 行で複雑な SELECT を書こうとすることです。

例えば、こんな感じです。

SELECT name, age
FROM users
WHERE age >= 20 AND email LIKE '%example.com'
ORDER BY age DESC
LIMIT 10;
SQL

もちろん、これでもいいのですが、
最初は「段階的に」考える方が分かりやすいです。

まずは、全件を見てみる。

SELECT * FROM users;
SQL

次に、「20 歳以上」に絞る。

SELECT * FROM users WHERE age >= 20;
SQL

さらに、「example.com のメール」に絞る。

SELECT * FROM users WHERE age >= 20 AND email LIKE '%example.com';
SQL

最後に、「欲しい列だけ」「並び順」「件数制限」を付ける。

SELECT name, age
FROM users
WHERE age >= 20 AND email LIKE '%example.com'
ORDER BY age DESC
LIMIT 10;
SQL

この「段階的に絞っていく」思考は、
Django の ORM でもそのまま役に立ちます。

「何が欲しいか」を日本語で言ってから SQL にする

SELECT を書く前に、
一度日本語で「欲しいもの」を言語化してみてください。

例えば、

「20 歳以上で、メールアドレスに example.com を含むユーザーの、名前と年齢を、年齢の高い順に 10 人だけ欲しい」

これをそのまま SQL に写経すると、こうなります。

どのテーブルから? → FROM users
どの列が欲しい? → SELECT name, age
どんな条件? → WHERE age >= 20 AND email LIKE ‘%example.com’
どんな順番? → ORDER BY age DESC
何件? → LIMIT 10

SQL は「日本語の要件を、決まった順番で並べ直したもの」だと考えると、
ぐっと書きやすくなります。


まとめ(SELECT を味方にすると、DB が「怖い箱」じゃなくなる)

SELECT を初心者目線でまとめると、こうなります。

どの列が欲しいか → SELECT
どのテーブルからか → FROM
どの行だけ欲しいか → WHERE
どんな順番で欲しいか → ORDER BY
何件まで欲しいか → LIMIT
重複を消したいか → DISTINCT
集計したいか → COUNT, SUM, AVG など(必要なら GROUP BY)

最初は、
小さな users テーブルを作って、

全件 SELECT
WHERE で条件を変えながら SELECT
ORDER BY で並び替え
LIMIT で件数を絞る

という練習を、自分の手で何度かやってみるのが一番早いです。

タイトルとURLをコピーしました