假设我有一个Parent
模型有很多Child
, 然后Child
也属于OtherParent
.
我怎样才能找到全部Parent
其中所有的Child
属于任何OtherParent
?
在纯 SQL 中我可以做
Parent.find_by_sql(<<SQL)
SELECT *
FROM parents p
WHERE NOT EXISTS (
SELECT *
FROM children
WHERE parent_id = p.id
AND other_parent_id IS NULL
)
SQL
(from here https://stackoverflow.com/questions/6430761/rails-how-to-query-for-all-the-objects-whose-every-association-have-an-attribut),但如果可能的话,我更愿意利用 ActiveRecord 来做到这一点。
Thanks!
我正在使用 Rails 4.2.1 和 PostgreSQL 9.3
Using arel
可以让你走得很远。棘手的部分是如何不使用编写整个查询arel
自己的查询语法?
这是一个技巧:使用以下命令构建查询时where
,如果你使用arel
有条件的话,你可以免费获得一些额外的方法。例如,您可以使用以下命令尾部子查询.exists.not
,这将为您带来(NOT ( EXISTS (subquery)))
把它扔进父母的where
- 条款,你就准备好了。
问题是,如何引用涉及的表?为此你需要阿雷尔。你could使用阿雷尔的where
及其丑陋的条件,例如a.eq b
。但为什么?由于它是一个相等条件,因此您可以使用 Rails 的条件来代替!您可以使用哈希键引用要查询的表,但对于其他表(在外部查询中),您可以使用其arel_table
。看这个:
parents = Parent.arel_table
Parent.where(
Child.where(other_parent_id: nil, parent_id: parents[:id]).exists.not
)
您甚至可以通过稍微求助于字符串并依赖于可以将子查询作为 Rails 的参数提供的事实来减少 Arel 的使用where
。它没有太多用处,但它不会强迫您过多地研究 Arel 的方法,因此您可以使用该技巧或其他采用子查询的 SQL 运算符(还有其他吗?):
parents = Parent.arel_table
Parent.where('NOT EXISTS (?)',
Child.where(parent_id: parents[:id], other_parent_id: nil)
)
这里的两个要点是:
- 您可以像构建常规查询一样构建子查询,使用 Arel 引用外部查询的表。它甚至可能不是一个真正的表,它可能是一个别名!疯狂的事情。
- 您可以使用子查询作为 Rails 的参数
where
方法就好了。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)