如何在 ARel 中执行完全联接?

Mat*_*ver 4 ruby activerecord arel

假设我有两个表,TableA并且TableB通过连接表具有多对多关系TableABJoin。我想用AREL 3生成一个查询,执行一个完整的加盟TableATableB

我想生成的查询应该是这样的:

SELECT a.id, b.code
FROM TableA as a, TableB as b
Run Code Online (Sandbox Code Playgroud)

这导致表 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
Run Code Online (Sandbox Code Playgroud)

这将产生以下 SQL:

SELECT "TableA"."id", "TableB"."code" FROM "TableA" LEFT OUTER JOIN "TableB" ON 1=1
Run Code Online (Sandbox Code Playgroud)

如果我排除.on组件,我最终会得到一个尾随 NULL:

SELECT "TableA"."id", "TableB"."code" FROM "TableA" LEFT OUTER JOIN "TableB" NULL
Run Code Online (Sandbox Code Playgroud)

是否有更合理的方法来生成正确的完全连接或至少生成相同的结果而不破解 ARel 中的左外连接?

Fir*_*DoL 5

实际上,不可能使用 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'
Run Code Online (Sandbox Code Playgroud)

在这里你可以看到一个语法示例:

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
Run Code Online (Sandbox Code Playgroud)