Ruby on rails ActiveRecord多重加入?
我正在努力解决活动记录加入问题 我有以下数据库表结构:Ruby on rails ActiveRecord多重加入?,ruby-on-rails,ruby,activerecord,join,Ruby On Rails,Ruby,Activerecord,Join,我正在努力解决活动记录加入问题 我有以下数据库表结构: A - B - C - D - E 及 我想从以下路径之一获取所有记录: A - B - C - D - E A - F - E 我们很满意 我用Active Record尝试了以下方法: A.joins(:B => {:C => {:D => :E}}, :F => :E) .where("some constraints on E and …") 但是,这不起作用,因为所有连接都生成为内部连接,如下所示:
A - B - C - D - E
及
我想从以下路径之一获取所有记录:
A - B - C - D - E
A - F - E
我们很满意
我用Active Record尝试了以下方法:
A.joins(:B => {:C => {:D => :E}}, :F => :E)
.where("some constraints on E and …")
但是,这不起作用,因为所有连接都生成为内部连接,如下所示:
SELECT A.*
FROM A
INNER JOIN B ON A.b_id = B.id
INNER JOIN C ON B.c_id = C.id
INNER JOIN D ON C.d_id = D.id
INNER JOIN E ON D.e_id = E.id
INNER JOIN F ON A.f_id = F.id
INNER JOIN E E_F ON E_F.f_id = F.id
WHERE ("some constraints on E")
我希望我没有在这里输入错误,但核心是,在生成的SQL语句中,两条路径都可以在ON子句中找到
问题是,要从表A返回记录,必须满足两个路径,对吗
我需要一个语句,用于返回两条路径的记录。
最后,它们通过uniq()
变得独一无二
我还尝试了merge()
两个单独的选择/连接(路径A-B-C-D-E”和“A-F-E”),但merge()进行交叉。
我提出的唯一解决方案是
+`两个独立的结果集,但问题是我得到一个数组作为结果,因此无法使用(kaminari)分页。
其次,当结果集越来越大时,这不是一个好的解决方案
如果有任何提示,我将不胜感激。
谢谢!我有一种感觉,您可能会在这里得到一个手工制作的巧妙连接:
SELECT A.*
FROM A
LEFT JOIN (B ON A.b_id = B.id
INNER JOIN C ON B.c_id = C.id
INNER JOIN D ON C.d_id = D.id
INNER JOIN E ON D.e_id = E.id)
LEFT JOIN (F ON A.f_id = F.id
INNER JOIN E E_F ON E_F.f_id = F.id)
WHERE E_F.id is not null or E.id is not null and
(„some constraints on E“)
当然,最好将其封装在一个范围内
通过F进行连接可能会遇到麻烦,因为它似乎是A和E的父级——如果F有多个E,那么A将返回多行
您可以通过使用相关子查询(半联接)来解决此问题:
请注意,可以从查询中删除F,因为F_ID在A和E中都存在
为了整洁起见,您可以使两个连接都成为半连接
SELECT A.*
FROM A
WHERE (EXISTS (SELECT NULL FROM E E_F WHERE E_F.F.id = A.F_ID) OR
EXISTS (SELECT NULL FROM B
INNER JOIN C ON B.c_id = C.id
INNER JOIN D ON C.d_id = D.id
INNER JOIN E ON D.e_id = E.id
WHERE A.b_id = B.id))
(„some constraints on E“)
把它放到一个范围内
scope :relates_to_e, -> {where("(EXISTS (SELECT NULL
FROM E E_F
WHERE E_F.F.id = A.F_ID) OR
EXISTS (SELECT NULL
FROM B
INNER JOIN C ON B.c_id = C.id
INNER JOIN D ON C.d_id = D.id
INNER JOIN E ON D.e_id = E.id
WHERE A.b_id = B.id))"}
这并不漂亮,但它将有效地工作,并将不整洁保持在一个范围内
A.relates_to_e.where(„some constraints on E and …“)
非常感谢您的提示!!!我需要的解决方案的核心是EXISTS-或composition。最后,我将作用域定义为带有参数的lambda。(我不想为所有细节打扰您;-)
scope :relates_to_e, -> {where("(EXISTS (SELECT NULL
FROM E E_F
WHERE E_F.F.id = A.F_ID) OR
EXISTS (SELECT NULL
FROM B
INNER JOIN C ON B.c_id = C.id
INNER JOIN D ON C.d_id = D.id
INNER JOIN E ON D.e_id = E.id
WHERE A.b_id = B.id))"}
A.relates_to_e.where(„some constraints on E and …“)