【SQL超入門講座】17.DISTINCT|重複した値を排除して抽出する方法

sql_17
SQL超入門講座

こんにちは、Kinocodeです。
皆さんは値の重複を排除してカラムを抽出したい時、どのようにしていますか?
以前の動画で解説したGROUP BY句を思いつく方が多いかもしれません。
このGROUP BY句と同じような機能を持つものとして、distinctがあります。
SELECT句でカラムの前にdistinctと書くだけで、値の重複を排除してそのカラムを抽出することができます。
とても便利ですので、GROUP BY句だけでなくdistinctも是非使えるようにしましょう。

この記事の執筆・監修

キノコード
キノコード

テクノロジーアンドデザインカンパニー合同会社のCEO。
日本最大級のプログラミング教育のYouTubeチャンネル「キノコード」や、プログラミング学習サービス「キノクエスト」を運営。
著書「あなたの仕事が一瞬で片付くPythonによる自動化仕事術」や、雑誌「日経ソフトウエア」や「シェルスクリプトマガジン」への寄稿など実績多数。

プログラミング学習サービス「キノクエスト」のご紹介

キノコードでは、プログラミングを習得するためのプログラミング学習サービス「キノクエスト」を運営しています。
Pythonの問題の他に、SQLの問題も120問以上あります。
キノクエストには、学習カリキュラムがあり、学習順番に悩むことなく学習を進められます。
月額1,990円と本1冊分の値段です。

キノクエストの特徴は下記の通りです。

  • SQLの問題も120問以上
  • プログラミング学習をしている仲間が集まるコミュニティがある
  • 1000問以上の問題を解いてプログラミングを習得
  • 環境構築不要ですぐに始められる
  • 動画と連動しているので、インプットもできる。
  • 月額1,990円で、コミュニティもセット

キノクエストを詳しく知りたい方は、紹介ページをご覧ください。

▼キノクエストの紹介ページはこちら▼
https://kino-code.com/kq_service_a/

それでは、レッスンスタートです。

distinctとは

distinctは値の重複を排除してカラムを抽出したいときに使います。
SELECT文では抽出するカラムの直前にdistinctを記述します。
distinctを追加したSELECT文の構文を確認しておきましょう。

SELECT distinct カラム1, カラム2... FROM テーブル

このようにしてdistinctを使って抽出したカラムには、一意の値だけが残ります。
そのためどのような値がカラムに存在しているか、一目瞭然で把握することができます。

distinctを使ったカラムの抽出

それではテーブルを作成して、distinctの使い方を具体的に見ていきましょう。
今回はproductsテーブルを使用します。
productsテーブルはid、category、item、priceの4つのカラムを持ったテーブルです。

まずdistinctを用いて、productsテーブルからcategoryのカラムを値の重複なしで抽出してみましょう。
SQLはこのように書くことができます。
抽出するcategoryのカラムの直前にdistinctと書けばOKです。
簡単ですね。

それでは実行します。

SELECT distinct category FROM products;

もともとproductsテーブルのcategoryには、outer、tops、shoesがそれぞれ2レコードずつ重複して存在していました。
distinctを使って抽出することで、これらの値の重複を排除して抽出することができました。

distinctを使った複数カラムの抽出

次にdistictを使って、複数のカラムをまとめて抽出してみましょう。
複数のカラムをまとめて抽出するときは、そのカラムに含まれる値の組み合わせの重複が排除されます。
言葉だけの説明だとわかりづらいと思いますので、さっそくSQLを書いて具体的に見ていきましょう。

ここではdistinctを使ってcategoryとitemのカラムをまとめて抽出してみます。
SQLはこのように書くことができます。
distinctは抽出する複数のカラムの先頭に書くようにしましょう。
それでは実行します。

SELECT distinct category, item FROM products;

抽出に使ったproductsテーブルを再度見てみましょう。
categoryとitemのカラムの値の組み合わせに注目してください。
そうするとshoesとsneakerの組み合わせに重複が見つかるはずです。

SQLの実行結果ではこのshoesとsneakerの値の組み合わせの重複が排除されています。
このようにdistinctを使って複数カラムをまとめて抽出すると、一意の値の組み合わせを表示することができます。

distinctをcountと併用する

今度はdistinctをcount関数と併用して使ってみましょう。

distictを使って抽出したカラムには一意の値だけが残ります。
このことは、ここまでの説明からご理解いただけているかと思います。

この一意の値は、カラムに存在する値の種類を表します。
これをカウントすることで、カラムに何種類の値が存在するかを調べることができます。

それでは、このようなSQLを書いて、categoryに何種類の値が存在するか調べてみましょう。

SELECT count(distinct category) FROM products;

categoryは重複を排除すると、outer, tops, shoesの3種類の値が存在しています。
これをcount関数で数えるので、実行結果には3が表示されます。

このようにdistinctとcount関数を併用することで、カラムに何種類の値が存在するかを簡単に調べることができます。

GROUP BY句との違い

最後にdistinctとGROUP BY句の違いを確認しておきましょう。
カラムを値の重複なしで抽出するために、distinctと別にGROUP BY句を使うこともできます。
distictよりGROUP BY句の方を、よく利用されている方も多いのではないでしょうか。

distinctを用いた抽出は、GROUP BY句で書き換え可能なケースがほとんどです。

しかしSQLの実行結果が同じでも、distinctとGROUP BY句では重複を排除する処理が異なります。
ここでは厳密な説明は行いませんが、「distinctは重複した値を排除」し、「GROUP BY句は重複した値を一つにまとめる」とイメージすると分かりやすいでしょう。

これを頭に入れた上で、最初に説明したSQLを見てみましょう。
このSQLではcategoryを値の重複なしで抽出しています。

SELECT distinct category FROM products;

このSQLはこのように、GROUP BY句で書き換えることができます。

SELECT category FROM products
GROUP BY category;

重複した値を除外しようが、一つにまとめようが、一意の値が抽出されることに変わりありません。
そのためカラムを値の重複なしで抽出するうえでは、distinctとGROUP BY句のどちらを使うこともできます。

一方でこのようなGROUP BY句を使った集計を、distinctで書き換えることはできません。

SELECT category, SUM(price) FROM products
GROUP BY category;

このSQLではGROUP BY句でcategoryのカラムを指定して、categoryのカラムの値ごとにpriceのカラムをSUM関数で集計しています。
distinctは特定のカラムをもとに集計するような処理には向いていません。
そのためこうした集計を行いたい時は、distinctではなく、GROUP BY句を使うようにしましょう。