2017-09-14 48 views
0

对于这个表:ActiveRecord的:过滤重复

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

我如何查询使用ActiveRecord此表(Rails的4.2,PostgreSQL的),如果得到的关系应该

  • 已填充的所有属性
  • 不包含重复名称
  • 宁愿将活动记录转为非活动记录
  • 能够调用.Count之间,其中count返回一个整数的
  • 保持一个ActiveRecord ::关系

正确的结果集应该是这样的:

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') 

回答

0

这应该工作

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

虽然计数的作品,这个查询的访问从关系中的元素失败,因为“的SELECT DISTINCT,ORDER BY表达式必须出现在选择列表' – tobmatth

+0

我不明白“关系元素”是什么意思? – meshin

+0

'User.select('DISTINCT name')。order('name,active DESC')。第一个' – tobmatth

0

也许

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

这将返回所有用户都具有占据的名称和积极的布尔(IDS将永远被组装)

然后在我们称之为

​​

这只是给了我们具有唯一名称的记录 最后

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

将启动时的记录设置为有效: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 } 
+0

使用uniq_by将要求将关系转换为数组,而我需要它保持关系。更新我的问题。 – tobmatth

+0

已更新的答案。 – Mark

+0

如果我不想错过任何东西,uniq是独立的别名,它需要一个.select存在(否则它会导致'SELECT DISTINCT users。*')。此外,sort_by转换为阵列 – tobmatth

0

既然你使用PostgreSQL,你可以使用DISTINCT ON。这里的SQL:

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

而且在活动记录:

>> 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">]> 
+0

这就是我已经尝试过,不幸的是我无法调用.count这个关系。 – tobmatth

+0

你是对的,我在阅读这个问题时错过了,我的错。虽然你可以调用'User.count_by_sql(User.order(name :: desc,active :: desc).select(“distinct on(name)*”))'',这是两个查询并且不满足原始问题。 –