假设我有一个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
(从此处开始),但我更愿意在可能的情况下利用ActiveRecord来实现。
谢谢!
我正在使用Rails 4.2.1和PostgreSQL 9.3
使用arel
可以使您走得更远。棘手的部分是如何不使用arel
自己的查询语法编写整个查询?
这是个窍门:使用进行查询时where
,如果使用arel
条件,则可以免费获得一些额外的方法。例如,您可以使用尾随具有的子查询.exists.not
,这将使您将(NOT ( EXISTS (subquery)))
Toss扔到父级的where
-clause中,就可以设置好了。
问题是,您如何引用所涉及的表?为此,您需要Arel。您可以使用Arel的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)
)
这里的两个要点是:
where
方法的参数。本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句