Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 如何选择不存在子项的记录_Ruby On Rails_Activerecord - Fatal编程技术网

Ruby on rails 如何选择不存在子项的记录

Ruby on rails 如何选择不存在子项的记录,ruby-on-rails,activerecord,Ruby On Rails,Activerecord,在rails中,我有两个表: bans(ban_id, admin_id) ban_reasons(ban_reason_id, ban_id, reason_id) 我想查找某个管理员的所有ban,其中ban\u原因表中没有记录。我如何在Rails中做到这一点,而不必遍历所有ban记录并过滤掉所有带有ban.ban\u reasons.nil的记录?我希望使用一条SQL语句来实现这一点 我只需要做:(但我想用“rails”的方式) ActiveRecord只能让您了解到一点,之后的一切都应该

在rails中,我有两个表:

bans(ban_id, admin_id)
ban_reasons(ban_reason_id, ban_id, reason_id)
我想查找某个管理员的所有
ban
,其中
ban\u原因
表中没有记录。我如何在Rails中做到这一点,而不必遍历所有ban记录并过滤掉所有带有
ban.ban\u reasons.nil的记录?
我希望使用一条SQL语句来实现这一点

我只需要做:(但我想用“rails”的方式)


ActiveRecord只能让您了解到一点,之后的一切都应该由原始SQL完成。AR的好处在于它使做这类事情变得非常容易

然而,自从Rails3以来,您几乎可以用ARELAPI做任何事情,尽管原始SQL看起来可能更可读,也可能不可读

我将使用原始SQL,如果您的查询性能不好,您可以尝试另一个查询:

SELECT       b.* 
FROM         bans b
LEFT JOIN    ban_reason br on b.ban_id = br.ban_id
WHERE        br.ban_reason_id IS NULL
您的解决方案非常有效(只有一个请求),但它几乎是纯SQL:

bans = Ban.where("bans.id NOT IN (SELECT ban_id from ban_reason)")
您还可以尝试以下操作,并让rails完成部分工作:

bans = Ban.where("bans.id NOT IN (?)", BanReason.select(:ban_id).map(&:ban_id).uniq)
使用gem(我是其作者):


两者之间有什么性能差异吗?第二个会导致更多的查询吗?是的,第二个会导致更多的查询…我认为性能问题实际上取决于您的数据库大小。我猜如果目标是使用Rails,无论代价如何,那么这个建议是可行的,但是,对于大型数据集来说,性能将受到可怕的影响。在大多数数据库上,这将比上面的另一个数据库性能更好。许多数据库的性能相当差(他们计算出了集合)。这对于在连接上搜索空值也会有一定的性能影响,但我仍然认为它可能比上面的更好。我认为将其实现为notexists()将是此查询更自然的语法,但我认为SQL是正确的。
bans = Ban.where("bans.id NOT IN (?)", BanReason.select(:ban_id).map(&:ban_id).uniq)
Ban.where(admin_id: 123).where_not_exists(:ban_reasons)