メインコンテンツへスキップ

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples on this page work on VillageSQL. Install Now →
SELECT DISTINCT は、各結果行が何回現れても、それを 1 回だけ返します。 「この列にはどんな値が現れるか」という形の質問に答えるもので、これは初めて 見るテーブルについて最初に知りたいことであることが多いものです。 始める前に、mysql -u root -p sakila でクライアントを開いてください。

DISTINCT の仕組み

COLUMN_LIST を欲しい列に、TABLE_NAME をテーブルに置き換えます。 DISTINCT は SELECT の直後に置かれ、隣の列ではなく選択リスト全体に適用 されます。この 1 つの事実が、これに関するほとんどの驚きを説明します。

例

  1. 1 つの列の値

Sakila はすべての映画にレーティングを付けています。これはどのレーティングが 存在するかを尋ねます。
1,000 本の映画にわたって 5 つのレーティングです。役に立つ順序では返って きません。DISTINCT は重複を取り除くだけで、順序については何も言わないため です。順序が欲しいときは ORDER BY を追加してください。

  1. 別の列

カタログ内のすべての映画は、3 つの料金のいずれかで価格が付けられています。

  1. 異なる組み合わせ

2 つの列を指定すると、各列の値を別々に得るのではなく、異なる組み合わせを それぞれ得ます。
5 つのレーティングに 3 つの料金を掛けると 15 で、たまたますべての組み合わせが 存在します。

並べ替えたレーティングがアルファベット順でない理由

その結果は rating で並べ替えられていますが、G、PG、PG-13、R、NC-17 の順に並んでいます。アルファベット順なら NC-17 は 2 番目に来るはずです。 ORDER BY は正しく動作しており、その理由は列の型にあります。 SHOW COLUMNS はテーブルの列を一覧にし、LIKE の後のパターンがそれを 1 つの 名前に絞り込みます。
rating は ENUM で、固定された値のリストだけを受け入れる列型です。MySQL は 各値をそのリスト内の位置として保存し、その位置で並べ替えるため、ENUM は値が 宣言された順序で並びます。ここでは、宣言された順序は最も制限の緩いレーティング から最も厳しいものへと並んでいます。

列を追加すると効果がなくなることがある

DISTINCT は行全体を見るため、ほぼ一意な列を追加すると、ほとんど何も 取り除かれません。
1,000 行すべてが返ります。各タイトルは異なるため、rating と title の各 組み合わせも異なり、重複するものは何もありません。ここで DISTINCT が 5 行を 返すことはできません。1,000 個の異なる値を持つ列を求めたからです。多くの行を レーティングごとに 1 行にまとめるのは別の操作であり、 GROUP BY がそのための句です。

まとめ

  • 各結果行を 1 回だけ返すには SELECT DISTINCT を使います。
  • 選択リスト内のすべての列に同時に適用されると考えてください。
  • 重複を除いた値を並べ替えたいときは ORDER BY を追加します。
  • ENUM 列はアルファベット順ではなく宣言された順序で並ぶと考えてください。

関連項目

  • SELECT — DISTINCT が修飾する文
  • ORDER BY — 重複を除いた値の並べ替え
  • GROUP BY — 行を値ごとに 1 行にまとめ、件数を付ける