ActiveRecord:过滤重复项

时间:2017-09-14 08:11:41

标签: ruby-on-rails rails-activerecord

鉴于此表:

Users
| id | name  | active |
| 1  | bob   | true   |
| 2  | bob   | false  |
| 3  | alice | false  |

如果结果关系应

,如何使用ActiveRecord(Rails 4.2,PostgreSQL)查询此表
  • 已填充所有属性
  • 不包含重复的名称
  • 更喜欢有效记录而不是非活动记录
  • 能够调用.count,其中count返回一个整数
  • 仍然是ActiveRecord :: Relation

正确的结果集应如下所示:

Users
| id | name  | active |
| 1  | bob   | true   |
| 3  | alice | false  |

到目前为止我尝试了什么:

# Works as for the result set, but raises when calling .count
User.select('DISTINCT ON (users.name) *')
    .order(users.name, users.active DESC')

3 个答案:

答案 0 :(得分:0)

这应该有效

User.select('DISTINCT name').order('name, active DESC').count

答案 1 :(得分:0)

也许

User.where.not(name: nil).where.not(active: nil)

这将返回具有填充名称和活动布尔值的所有用户(将始终填充ID)

然后我们打电话给

.uniq_by(:name)

这只给我们带有唯一名称的记录 最后

.sort_by { |a| a.active ? 1 : 0 }

将记录设置为active:true。所以方法是:

User.where.not(name: nil).where.not(active: nil).uniq_by(:name).sort_by { |a| a.active ? 1 : 0 }

在这个查询中,我们可以调用count来获取对象的数量。

编辑:

保持AR将uniq_by更改为uniq:

User.where.not(name: nil).where.not(active: nil).uniq(name).sort_by { |a| a.active ? 1 : 0 }

答案 2 :(得分:0)

由于您正在使用PostgreSQL,因此您可以使用DISTINCT ON。这是SQL:

select distinct on (name) * from users order by name, active desc

在Active Record中:

>> User.order(name: :desc, active: :desc).select("distinct on (name) *")
  User Load (2.5ms)  SELECT  distinct on (name) * FROM "users" ORDER BY "users"."name" DESC, "users"."active" DESC LIMIT $1  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 2, name: "bob", active: true, created_at: "2017-09-15 03:58:23", updated_at: "2017-09-15 03:58:23">, #<User id: 3, name: "alice", active: false, created_at: "2017-09-15 03:58:35", updated_at: "2017-09-15 03:58:35">]>