LoginSignup
63
55

More than 3 years have passed since last update.

Rails distinctメソッドについて

Posted at

distinctメソッド

distinctメソッドとは重複レコードを1つにまとめるためのメソッドです。もともとはuniqというメソッドが同じ機能で使えていたようですがRails5になってからはdistinctメソッドを使うように決められているようです。(uniqメソッドは非推奨もしくは使用不可に変更されているようです。)

Railsのdistinctの使い方に関してはっきり分からなかったので自分で検証して確認してみることにします。今回はrails cを使ってモデルを作成して検証します。前準備として、

rails new distinct_app
rails g model User last_name:string first_name:string birthday:date age:integer

として、アプリケーションを作成してモデルも作成します。その後、rails cでコンソールモードにしてコマンドでデータを作成していきます。

User.create(last_name: "Toda", first_name: "Hiroyuki", birthday: "1988-08-17", age:31)
User.create(last_name: "Suzuki", first_name: "Hiroyuki", birthday: "1988-08-17", age:31)
User.create(last_name: "Woda", first_name: "Hiroyuki", birthday: "1988-08-17", age:31)
User.create(last_name: "Toda", first_name: "Hiroyuki", birthday: "1988-06-01", age:31)
User.create(last_name: "Toda", first_name: "Taro", birthday: "1988-06-01", age:31)
User.create(last_name: "Toda", first_name: "Ichiro", birthday: "1988-06-01", age:31)
User.create(last_name: "Toda", first_name: "Hanako", birthday: "1988-06-01", age:31)

というようにUserモデルを作成します。その後、コマンドで

User.select(:first_name, :age).distinct

とすると、

=> #<ActiveRecord::Relation 
[#<User id: nil, first_name: "Hiroyuki", age: 31>,
 #<User id: nil, first_name: "Taro", age: 31>,
 #<User id: nil, first_name: "Ichiro", age: 31>,
 #<User id: nil, first_name: "Hanako", age: 31>]
>

という結果が返ってきて問題なさそうです。

distinctはselectしなくても問題ないか?

User.distinct(:first_name)

のように書いて、first_nameカラムが重複しないようになるか試してみました。結果は

=> #<ActiveRecord::Relation [
#<User id: 1, last_name: "Toda", first_name: "Hiroyuki", birthday: "1988-08-17", age: 31, created_at: "2019-09-13 01:49:32", updated_at: "2019-09-13 01:49:32">,
#<User id: 2, last_name: "Suzuki", first_name: "Hiroyuki", birthday: "1988-08-17", age: 31, created_at: "2019-09-13 01:49:44", updated_at: "2019-09-13 01:49:44">,
#<User id: 3, last_name: "Woda", first_name: "Hiroyuki", birthday: "1988-08-17", age: 31, created_at: "2019-09-13 01:49:54", updated_at: "2019-09-13 01:49:54">, 
#<User id: 4, last_name: "Toda", first_name: "Hiroyuki", birthday: "1988-06-01", age: 31, created_at: "2019-09-13 01:50:46", updated_at: "2019-09-13 01:50:46">, 
#<User id: 5, last_name: "Toda", first_name: "Taro", birthday: "1988-06-01", age: 31, created_at: "2019-09-13 01:52:16", updated_at: "2019-09-13 01:52:16">, 
#<User id: 6, last_name: "Toda", first_name: "Ichiro", birthday: "1988-06-01", age: 31, created_at: "2019-09-13 01:52:24", updated_at: "2019-09-13 01:52:24">, 
#<User id: 7, last_name: "Toda", first_name: "Hanako", birthday: "1988-06-01", age: 31, created_at: "2019-09-13 01:52:33", updated_at: "2019-09-13 01:52:33">]>

となりました。これだと重複が防げてないですね。。どうやら一度selectしてからdistinctを実行する必要があるみたいです。

まとめ

distinctコマンドは内部的にはSQLのDISTINCTコマンドを呼び出しています。個人的に何となくselectしなくても重複を避けられると思っていたので、今回の検証の結果は意外なものでした。distinctする場合は、selectとしてから...忘れないようにします。

63
55
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
63
55