查找具有重复名称的所有用户

时间:2010-12-30 17:10:17

标签: ruby-on-rails ruby activerecord

我的用户有first_name和last_name字段,我需要做一个ruby,根据名字和姓氏查找所有拥有重复帐户的用户。例如,我希望有一个搜索将搜索所有其他用户,并查找是否有任何相同的名称和电子邮件。我在想一个像这样的嵌套循环

User.all.each do |user|
 //maybe another loop to search through all the users and maybe if a match occurs put that user in an array
end

有没有更好的方式

3 个答案:

答案 0 :(得分:33)

通过首先找出重复数据的内容,您可以大大缩小搜索范围。例如,假设您要查找多次使用的名字和电子邮件的每个组合。

User.find(:all, :group => [:first, :email], :having => "count(*) > 1" )

这将返回一个包含每个重复记录之一的数组。据说,其中一个返回的用户有“Fred”和“fred@example.com”,那么您只能搜索具有这些值的用户来查找所有受影响的用户。

find的回复将如下所示。请注意,该数组仅包含每组重复用户的单个记录。

[#<User id: 3, first: "foo", last: "barney", email: "foo@example.com", created_at: "2010-12-30 17:14:43", updated_at: "2010-12-30 17:14:43">, 
 #<User id: 5, first: "foo1", last: "baasdasdr", email: "abc@example.com", created_at: "2010-12-30 17:20:49", updated_at: "2010-12-30 17:20:49">]

例如,该数组中的第一个元素显示一个用户使用“foo”和“foo@example.com”。其余的可以根据需要通过查找从数据库中取出。

> User.find(:all, :conditions => {:email => "foo@example.com", :first => "foo"})
 => [#<User id: 1, first: "foo", last: "bar", email: "foo@example.com", created_at: "2010-12-30 17:14:28", updated_at: "2010-12-30 17:14:28">, 
     #<User id: 3, first: "foo", last: "barney", email: "foo@example.com", created_at: "2010-12-30 17:14:43", updated_at: "2010-12-30 17:14:43">]

而且您似乎还希望为代码添加一些更好的验证,以防止将来出现重复。

编辑:

如果您需要使用find_by_sql的大锤,因为Rails 2.2及更早版本不支持:having find,以下内容应该可以使用,并为您提供相同的数组我在上面描述过。

User.find_by_sql("select * from users group by first,email having count(*) > 1")

答案 1 :(得分:0)

经过一些谷歌搜索后,我最终得到了这个:

ActiveRecord::Base.connection.execute(<<-SQL).to_a
  SELECT 
    variants.id, variants.variant_no, variants.state 
  FROM variants INNER JOIN (
    SELECT 
      variant_no, state, COUNT(1) AS count 
    FROM variants
    GROUP BY 
      variant_no, state HAVING COUNT(1) > 1
  ) tt ON 
    variants.variant_no = tt.variant_no 
    AND variants.state IS NOT DISTINCT FROM tt.state;
SQL

请注意标注IS NOT DISTINCT FROM的部分,这是为了帮助处理NULL值,而这些值无法与postgres中的等号进行比较。

答案 2 :(得分:0)

如果您要使用@hakunin的路线并手动创建查询,您可能希望使用以下内容:

ActiveRecord::Base.connection.exec_quey(<<-SQL).to_a
  SELECT 
    variants.id, variants.variant_no, variants.state 
  FROM variants INNER JOIN (
    SELECT 
      variant_no, state, COUNT(1) AS count 
    FROM variants
    GROUP BY 
      variant_no, state HAVING COUNT(1) > 1
  ) tt ON 
    variants.variant_no = tt.variant_no 
    AND variants.state IS NOT DISTINCT FROM tt.state;
SQL

更改正在取代connection.execute(<<-SQL)connection.exec_query(<<-SQL)

使用execute

可能会导致内存泄漏问题

请阅读Clarify DataBaseStatements#execute以深入了解问题。