たまにデータベースって、記憶力が悪い人みたいな感じしない?全部メモるけど、すでに書いたことを忘れちゃう。で、クライアントの都市のテーブルを開くと、「ベルリン」が10個、「シアトル」が5個、他にも同じのがいっぱい。これは、同じ都市が違うクライアントで何回も出てくるからなんだよね。でも、広告キャンペーンを「ベルリン」10個分で作りたいわけじゃなくて、1都市分だけでいいでしょ?
ユニークな値だけを取り出したい時――重複なしで――便利なのが DISTINCT コマンド。まるで魔法のモップみたいに、一振りで重複行を消して、本当に違うものだけ残してくれる。
DISTINCT を使うと、クエリの結果からユニークな行だけを抽出できる。これは、例えばこんな重複データを消したい時に便利:
- 注文内のユニークな商品。
- ユニークなクライアント名。
- 「都市+国」みたいなユニークなデータの組み合わせ。
DISTINCT はどう動く?
DISTINCT のシンタックスは超シンプルで分かりやすい。SQLってだいたいそうだよね:
SELECT DISTINCT カラム1, カラム2, ...
FROM テーブル;
クエリに DISTINCT を追加すると、データベースは結果の各行がユニークになるようにしてくれる。
DISTINCT の使い方例
まずはクラシックな例から、DISTINCT がどう動くか見てみよう。
例1:1つのカラムのユニークな値
例えば、students という学生データのテーブルがあるとする:
-- テーブル students
| id | first_name | last_name | city |
|---|---|---|---|
| 1 | Maria | Chi | Seattle |
| 2 | Alex | Lin | Toronto |
| 3 | Anna | Song | Seattle |
| 4 | Nat | Cole | Chicago |
| 5 | Maria | Chi | Seattle |
学生たちがどの都市から来てるか知りたいとき、こう書く:
SELECT city
FROM students;
で、結果はこう:
| city |
|---|
| Seattle |
| Toronto |
| Seattle |
| Chicago |
| Seattle |
ちょっと思ってたのと違う :(
重複を消したいなら DISTINCT を使う:
SELECT DISTINCT city
FROM students;
結果:
| city |
|---|
| Seattle |
| Toronto |
| Chicago |
DISTINCT なしだと「Seattle」が3回出てくるけど、欲しいのは1回だけだよね。
例2:複数カラムのユニークな値
今度は、「名前+苗字」のユニークな組み合わせを取得したいとする。学生の中には同じ苗字や名前の人もいるかもしれないし。
同じく students テーブルを使う:
-- テーブル students
| id | first_name | last_name | city |
|---|---|---|---|
| 1 | Maria | Chi | Seattle |
| 2 | Alex | Lin | Toronto |
| 3 | Anna | Song | Seattle |
| 4 | Nat | Cole | Chicago |
| 5 | Maria | Chi | Seattle |
クエリ:
SELECT DISTINCT first_name, last_name
FROM students;
結果:
| first_name | last_name |
|---|---|
| Maria | Chi |
| Alex | Lin |
| Anna | Song |
| Nat | Cole |
こんな感じで、DISTINCT はフィルターみたいに動く。指定したカラム全部を見て、全部の値が同じ行だけ重複として消してくれる。
例3:ユニークな組み合わせ+ソート
今度は DISTINCT と ORDER BY を組み合わせて、ユニークな値を苗字のアルファベット順で並べてみよう。
またまた students テーブル:
-- テーブル students
| id | first_name | last_name | city |
|---|---|---|---|
| 1 | Maria | Chi | Seattle |
| 2 | Alex | Lin | Toronto |
| 3 | Anna | Song | Seattle |
| 4 | Nat | Cole | Chicago |
| 5 | Maria | Chi | Seattle |
クエリ:
SELECT DISTINCT first_name, last_name
FROM students
ORDER BY last_name ASC;
結果:
| first_name | last_name |
|---|---|
| Maria | Chi |
| Nat | Cole |
| Alex | Lin |
| Anna | Song |
重複行は消えて、苗字はアルファベット順に並んでる。
例4:集計関数で使う
じゃあ、DISTINCT を COUNT みたいな関数で使ったらどうなる?
SELECT COUNT(DISTINCT city) AS unique_city_count
FROM students;
結果:
| unique_city_count |
|---|
| 3 |
このクエリはユニークな都市の数を返してくれる。便利だよね?
DISTINCT の動作の特徴
DISTINCT を使うときは、指定したカラム全部でユニークかどうかが決まるってことを理解しておこう。クエリにカラムを増やすと、結果も変わるかも。
例5:なぜコンテキスト理解が大事?
クエリに追加のフィールドを入れると、行のユニークさに影響することがある。
SELECT DISTINCT first_name, city
FROM students;
students テーブル:
| id | first_name | last_name | city |
|---|---|---|---|
| 1 | Maria | Chi | Seattle |
| 2 | Alex | Lin | Austin |
| 3 | Anna | Song | Seattle |
| 4 | Otto | Art | Denver |
| 5 | Maria | Chi | Portland |
結果:
| first_name | city |
|---|---|
| Maria | Seattle |
| Alex | Austin |
| Anna | Seattle |
| Otto | Denver |
| Maria | Portland |
「名前+都市」の組み合わせが全部ユニークになってる。だから覚えておこう:ユニークさは指定した全カラムで決まる、1つ1つのカラムじゃないよ。
DISTINCT でよくあるミス
DISTINCT を使うときの一番ありがちなミスは、クエリが何をしてるかちゃんと理解してないこと。例えば、カラムを多く指定しすぎると、思ってたのと全然違う結果になることがある。なぜなら、全部のカラムでユニークかどうかが決まるから。
例えば:
SELECT DISTINCT *
FROM students;
この場合、全カラムが考慮されるから、各行が全部ユニーク扱いになる。
もう一つのミスは、DISTINCT がいらない場面で使っちゃうこと。例えば、すでにユニークなデータ(主キーのカラムとか)なら、DISTINCT はDBに余計な負荷をかけるだけ。
GO TO FULL VERSION