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

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

この記事の信頼性

この記事は、Youtubeにて日本最大級のプログラミング教育のチャンネルを運営しているキノコードが執筆、監修しています。
私自身は、2012年からプログラミング学習を始め、2019年以降はプログラミング教育に携わってきた専門家です。
他にも、私には下記のような実績や専門性があります。

  • キノコードは毎月10名以上、合計100名以上ののプログラミング学習者と1対1でお悩みを聞き、アドバイスをしています
  • キノコード自身は、プログラミングスクールに通ったり、本や有料åの動画で勉強してきた経験もあります
  • キノコードは、プログラミング学習サービス「キノクエスト」を運営しています
  • 本の出版、プログラミング雑誌への寄稿の実績があります

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

キノコードでは、プログラミングを習得するためのプログラミング学習サービス「キノクエスト」を運営しています。
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句を使うようにしましょう。