スライドショー

【Rails入門】uniqで重複が無いモデルにしよう!distinctにも対応

こんにちは!システムエンジニアのオオイシです。

今回は、Ruby on Railsのuniqメソッドをご存じですか!?

uniqメソッドを使うと、

重複レコードを1つにまとめて取得

SQLのDISTINCTをRailsで実行

などの課題を解決できます。

そこで今回は以下の内容について解説していきます。

【基礎】uniqメソッドとは?distinctとの違い
【基礎】uniq(distinct)メソッドの構文
【基礎】uniq(distinct)メソッドを使ってみよう!
【応用】uniq(distinct)メソッドの実用的な使い方を紹介

初心者でもわかるように解説していますので、しっかりと理解しておきましょう!

uniqメソッドとは?distinctとの違い

uniqメソッドとは、Railsで取得した重複レコードを1つにまとめるためのメソッドです。

uniqメソッドを実行すると、Railsは内部的にSQLのDISTINCTを実行します。

その他に、uniqメソッドとまったく同じ働きをするdistinctメソッドも存在します。

両者の違いは、

  • uniqメソッド   → Rails5以降で非推奨(または使えなくなる)
  • distinctメソッド → Rails5以降で正式メソッド

となっているので注意しましょう!

そのため、これからはdistinctメソッドを使うようにしてください。

本記事でもdistinctメソッドで解説します。

なお、SQLのDISTINCTについては、こちらで詳しく解説しているため、ぜひ参考にしてください。

【SQL入門】DISTINCTで重複行をまとめる方法をわかりやすく解説
更新日 : 2019年4月23日

uniq(distinct)メソッドの構文

構文は次の通りです。

  • モデル.select(列名).distinct

Railsのログを確認するとこのようなSQLが実行されます。

Railsが実行するSQL:

SELECT S DISTINCT `テーブル名`.`列名` FROM `テーブル名`

次項では、distinctメソッドの使い方を詳しく解説していきます。

uniq(distinct)メソッドを使ってみよう!

ここでは、distinctメソッドの使い方をサンプルコードを使って解説します。

姓(last_name)名(first_name)のカラムをもつSampleモデルを作成し、distinctメソッドの動きを確認してみましょう。

サンプルモデルの作成

はじめに、Sampleモデルを作成します。

$ bin/rails g model sample last_name:string first_name:string
Running via Spring preloader in process 19028
      invoke  active_record
      create    db/migrate/20180826112329_create_samples.rb
      create    app/models/sample.rb
$ bin/rake db:migrate

rails コンソールでテストデータを投入します。

$ bin/rails c
> Sample.create!(last_name: "侍", first_name: "太郎")
> Sample.create!(last_name: "侍", first_name: "次郎")
> Sample.create!(last_name: "侍", first_name: "花子")
> Sample.create!(last_name: "侍", first_name: "太郎")
> Sample.all
+----+-----------+------------+-------------------------+-------------------------+
| id | last_name | first_name | created_at              | updated_at              |
+----+-----------+------------+-------------------------+-------------------------+
| 1  | 侍        | 太郎       | 2018-08-27 06:15:04 UTC | 2018-08-27 06:15:04 UTC |
| 2  | 侍        | 次郎       | 2018-08-27 06:15:35 UTC | 2018-08-27 06:15:35 UTC |
| 3  | 侍        | 花子       | 2018-08-27 06:15:43 UTC | 2018-08-27 06:15:43 UTC |
| 4  | 侍        | 太郎       | 2018-08-27 06:15:47 UTC | 2018-08-27 06:15:47 UTC |
+----+-----------+------------+-------------------------+-------------------------+
4 rows in set

登録したサンプルデータを使って、distinctメソッドを使ってみましょう。

なお、RailsコンソールでActive Recordの検索結果を一覧で確認できるようにするために、HirbというGemを使っています。

こちらに解説があるので参考にしてみてください。

【Rails入門】初心者が知っておくべき3つのgem
更新日 : 2019年8月9日

Railsのモデルについてはこちらで詳しく解説しています。

uniq(distinct)メソッドの使い方

準備が整いましたので、distinctメソッドを使って、姓(last_name)重複をまとめて表示するサンプルコードを見てみましょう。

使い方はとっても簡単です!

distinctを使わない場合:

> Sample.select(:last_name)
  Sample Load (1.3ms)  SELECT `samples`.`last_name` FROM `samples`
+----+-----------+
| id | last_name |
+----+-----------+
|    | 侍        |
|    | 侍        |
|    | 侍        |
|    | 侍        |
+----+-----------+
4 rows in set

distinctを使う場合:

> Sample.select(:last_name).distinct
  Sample Load (0.8ms)  SELECT DISTINCT `samples`.`last_name` FROM `samples`
+----+-----------+
| id | last_name |
+----+-----------+
|    | 侍        |
+----+-----------+
1 row in set
irb(main):006:0>

このように、重複がないレコードが取得できました。

次項では、distinctメソッドの応用的な使いかたを紹介していきます!

uniq(distinct)メソッドの実用的な使い方を紹介

複数列でdistinctメソッドを使う

複数の列を指定してdistinctした場合には、複数列を合わせてユニークになるように重複がまとめられます。

  • モデル.select(列名,列名...).distinct

姓(last_name)名(first_name)の2列に対してdistinctするサンプルコードを確認して見ましょう。

distinctを使わない場合:

> Sample.select(:last_name,:first_name)
  Sample Load (0.5ms)  SELECT `samples`.`last_name`, `samples`.`first_name` FROM `samples`
+----+-----------+------------+
| id | last_name | first_name |
+----+-----------+------------+
|    | 侍        | 太郎       |
|    | 侍        | 次郎       |
|    | 侍        | 花子       |
|    | 侍        | 太郎       |
+----+-----------+------------+
4 rows in set

distinctを使う場合:

> Sample.select(:last_name,:first_name).distinct
  Sample Load (0.7ms)  SELECT DISTINCT `samples`.`last_name`, `samples`.`first_name` FROM `samples`
+----+-----------+------------+
| id | last_name | first_name |
+----+-----------+------------+
|    | 侍        | 太郎       |
|    | 侍        | 次郎       |
|    | 侍        | 花子       |
+----+-----------+------------+
3 rows in set

このように、複数列で重複のないレコードを取得することができました。

distinctして件数を調べるには

distinctを使ってレコード件数を数える方法について紹介します。

モデルのデータ件数を数えるためにsizeメソッドがありますが、これを組み合わせて件数を取得します。

  • モデル.select(列名,列名...).distinct.size

重複のない姓(last_name)の件数を調べる、サンプルコードを確認して見ましょう。

distinctを使わない場合:

> Sample.select(:last_name).size
   (0.2ms)  SELECT COUNT(*) FROM `samples`
=> 4

distinctを使う場合:

> Sample.select(:last_name).distinct.size
   (0.6ms)  SELECT COUNT(*) FROM (SELECT DISTINCT `samples`.`last_name` FROM `samples`) subquery_for_count
=> 1

このように、レコードの件数を数えることができました。

rubyの配列にはuniqメソッドを使う

Rubyの配列には、重複を1つにまとめるuniqメソッドがあるため、こちらも紹介します。

姓(last_name)のレコードを配列で取得して、uniqメソッドで重複のない配列を取得するサンプルコードを確認して見ましょう。

uniqを使わない場合:

> Sample.pluck(:last_name)
   (0.4ms)  SELECT `samples`.`last_name` FROM `samples`
=> ["侍", "侍", "侍", "侍"]

uniqを使う場合:

> Sample.pluck(:last_name).uniq
       (0.3ms)  SELECT `samples`.`last_name` FROM `samples`
=> ["侍"]

このように重複のない配列を取得することができました。

なお、pluckの使い方については、こちらで詳しく解説しているのでぜひ参考にしてください。

【Rails入門】pluckの使い方まとめ
更新日 : 2019年5月10日

まとめ

いかかでしたか?

今回は、Railsのuniq(distinct)メソッドの使い方をについて解説しました。

uniq(distinct)メソッドは、Railsで取得した重複レコードを1つにまとめるためのメソッドです。

uniq(distinct)メソッドを使うと、Rails内部ではSQLのDISTINCTが実行されるため、何かと利用頻度の多いメソッドです。

uniq(distinct)メソッドの使い方を忘れてしまったらこの記事を確認してくださいね!

LINEで送る
Pocket

無料でSEからWebエンジニアへ転職しませんか?



侍エンジニア塾では、完全未経験の方から現在SEだけどプログラミングはやっていないという経験者まで、幅広い方々の人生を好転させるプログラミング指導を行ってきました。SEの方とお話していくなかで、

  • システムエンジニアという職業だけどコードが書けない
  • 事務作業が多くスキルがないため将来が不安
  • スクールに通うと完全未経験者と同じスタートになるからレベルが合わない
という、すでに知識があるSEならではのお悩みがあることに気づきました。そんな方におすすめなのが、弊社の「転職コース 」です。

弊社では、マンツーマンでレッスンを行いますので、現在お持ちの知識レベルからカリキュラムを作成いたします。さらにこちらの転職コースは無料で受講を始められて転職成功でそのまま卒業できるというとてもお得なコースとなっています。

既に知識のあるSEといっても転職は年齢が若いほど受かりやすいため、まずは無料体験レッスンで今の現状や理想の働き方について一緒に考えていきましょう。

まずは無料体験レッスンを予約する

書いた人

オオイシ

オオイシ

システムエンジニア歴15年のオオイシです!好物は Java と Ruby。プログラミング、システムアーキテクトからマネジメントに到るまでなんでも食べます。
システム開発の相談やお困りごとがあればお気軽に
[email protected] まで連絡頂けると幸いです

おすすめコンテンツ

あなたにぴったりなプログラミング学習プランを無料で診断!

プログラミング学習の効率を劇的に上げる学習メソッドを解説