2012-02-05 46 views
0

例如,我有2个表格:主题和注释。加入表格 - Rails 3中的关联

主题has_many评论。评论属于主题。

评论表有专栏sender_id我保存用户的ID,谁创建此评论。

任务:选择未由该用户评论的主题的id(我知道user_id)。 (我想用一个查询来完成)。

早些时候我这样做。 (两个查询)(我的数据库 - PostgreSQL的)

incorrect_topics = Comment.select(:topic_id).where(:sender_id => user_id).map { |elem| elem.topic_id } 
ids = select(:id).where(["id NOT IN (?)", incorrect_topics]).map { |elem| elem.id } 

它工作正常,但我想,如果应用程序变大这将是严重的问题。

谢谢。

回答

1

如果你需要的是ID的,那么你可以绕过所有ActiveRecord的东西,用手做:

ids = connection.select_rows(%Q{ 
    select id 
    from topics 
    where id not in (
     select topic_id 
     from comments 
     where sender_id = #{user_id.to_i} 
    ) 
}).map { |r| r.first.to_i } 

如果你是一定的user_id已经是整数,那么你不需要.to_i。您也可以使用#{connection.quote(user_id)}。如果您想避免用map手动解开行,您也可以使用与select_values相同的SQL。

如果你想要的主题实例然后find_by_sql将是一种选择:

topics = find_by_sql(%q{ 
    select * 
    from topics 
    where id not in (
     select topic_id 
     from comments 
     where sender_id = :user_id 
    ) 
}, :user_id => user_id) 

有些东西更清晰,当你直接使用SQL比当您尝试包起来的东西的ActiveRecord。

+0

我没有尝试,但它必须工作。但是,我可以做不通过查询中的查询。但只有一个查询?不能加入帮助我吗? JOIN可以更快吗? – makrusak 2012-02-05 09:24:29

+1

@ rusak1:查询优化器将知道如何处理这样的简单查询,并且它具有清晰的优势。 – 2012-02-05 09:39:51

+0

最后一个问题:您对JOIN有什么看法?它快吗?数据库很难吗? – makrusak 2012-02-05 09:45:04

0

也许这样的事情可以工作:

incorrect_topics = Comment.where('sender_id <> ?', user_id).topics 

让我知道如果反正可以帮助你。

+1

考虑用户1和用户2对主题3,Comment.where('sender_id <>?',user_id)进行了评论,即使用户2对其进行了评论,.topics也会为您提供主题3。 – 2012-02-05 09:02:26

+0

Kleber S.,谢谢你的变体,但它是不正确的。亩太短是正确的。 – makrusak 2012-02-05 09:13:28