假设我有两个表TableA
和TableB
,它们通过连接表TableABJoin
具有多对多关系。我想使用ARel 3生成一个执行TableA
和TableB
完整联接的查询。
我想要生成的查询应该是以下几行:
SELECT a.id, b.code
FROM TableA as a, TableB as b
这导致表A和B的完全连接。
在没有编写明确的sql字符串的情况下,我能够获得的最接近的是破解外连接:
part_a = TableA.arel_table
part_b = TableB.arel_table
query = part_a.join(part_b, Arel::Nodes::OuterJoin).on('1=1').project(part_a[:id], part_b[:code]).to_sql
这会生成以下SQL:
SELECT "TableA"."id", "TableB"."code" FROM "TableA" LEFT OUTER JOIN "TableB" ON 1=1
如果我排除了.on
组件,我最终会得到一个尾随的NULL:
SELECT "TableA"."id", "TableB"."code" FROM "TableA" LEFT OUTER JOIN "TableB" NULL
是否有更合理的方法来生成正确的完全连接或至少生成相同的结果而不在ARel中破坏左外连接?
答案 0 :(得分:4)
实际上,无法使用arel执行完全外连接(和右外连接),arel仅支持内部和外部(LEFT OUTER)连接。
因为我不喜欢这个,我更新了arel 3-0-stable(我正在使用3.2.13 rails应用程序),所以它也支持右外连接和全外连接。即使使用未记录的代码,添加它们也非常简单,这很容易,所以如果你尝试它就不会遇到任何问题。
您可以在此处找到我的拉取请求:https://github.com/rails/arel/pull/202
在这里,您可以找到带有分支的更新存储库:https://github.com/Fire-Dragon-DoL/arel/tree/3-0-right-full-outer-join
您可以通过将其添加到Gemfile中轻松地在rails应用程序中使用它:
gem 'arel', '~> 3.0.3.4', github: 'Fire-Dragon-DoL/arel', branch: '3-0-right-full-outer-join'
在这里你可以看到一个语法示例:
class Cat < ActiveRecord::Base
has_many :cat_diseases
end
class Disease < ActiveRecord::Base
has_many :cat_diseases
end
class CatDisease < ActiveRecord::Base
belongs_to :cat
belongs_to :disease
def self.all_diseases_for_cat(cat)
cat_diseases = self.arel_table
diseases = Disease.arel_table
scoped
.joins(
cat_diseases.join(diseases, Arel::Nodes::RightOuterJoin)
.on(cat_diseases[:disease_id].eq(diseases[:id]))
.join_sources
)
.where(
cat_diseases[:cat_id].eq(cat.id)
.or(cat_diseases[:cat_id].eq(nil))
)
end
end
答案 1 :(得分:0)
我在SQL中编写了连接。它更清晰,工作正常:
part_a = TableA.arel_table
part_b = TableB.arel_table
query = part_a.joins('LEFT OUTER JOIN "TableB"').other_scopes.to_sql