Rails 使用别名查询连接关联表

Posted

技术标签:

【中文标题】Rails 使用别名查询连接关联表【英文标题】:Rails query join association table with alias 【发布时间】:2015-06-05 04:55:06 【问题描述】:

我有一个模型 Edge 通过不同的外键两次属于另一个模型 Node

def Edge < ActiveRecord::Base
    belongs_to :first, class_name: 'Node'
    belongs_to :second, class_name: 'Node'
end

我想使用 ActiveRecord 执行此查询:

SELECT * FROM edges INNER JOIN nodes as first ON first.id = edges.first_id WHERE first.value = 5

我找到了使用.joins()方法加入协会的方法:

Edge.joins(:first)

但这会产生使用表名而不是关联名的查询,因此在.where() 方法中我必须显式使用破坏关联抽象的表名。

Edge.joins(:first).where(nodes: value: 5)

我也可以在.joins()方法中显式使用SQL查询来定义模型别名:

Edge.joins('INNER JOIN nodes as first ON nodes.id = edges.first_id')

但这打破了更多的抽象。

我认为应该有在连接时自动定义表别名的方法。或者也许是我自己编写这样的功能的一种方式。比如:

def Edge < ActiveRecord::Base
    ...
    def self.joins_alias
        # Generate something like 
        # joins("INNER JOIN #relation.table as #relation.alias ON #relation.alias.#relation.primary_key = #table.#relation.foreign_key")
    end
end

但是我找不到任何有关访问特定关系信息的信息,例如它的名称、外键等。那么我该怎么做呢?

我也觉得奇怪,即使 Rails 已经是第 4 个主要版本,如此明显的功能却如此复杂。也许我错过了什么?

【问题讨论】:

【参考方案1】:

对于 Rails 4.2.1,我相信您在使用 ActiveRecord 中的joins 时无法提供别名。

如果你想通过第一个节点查询边,你可以像你说的那样做:

Edge.joins(:first).where(nodes: value: 1)
SELECT "edges".* FROM "edges" INNER JOIN "nodes" ON "nodes"."id" = "edges"."first_id" WHERE "nodes"."value" = 1

但如果你必须同时使用两个节点进行查询,你仍然可以像这样使用joins

Edge.joins(:first, :second).where(nodes: value: 1, seconds_edges: value: 2)
SELECT "edges".* FROM "edges" INNER JOIN "nodes" ON "nodes"."id" = "edges"."first_id" INNER JOIN "nodes" "seconds_edges" ON "seconds_edges"."id" = "edges"."second_id" WHERE "nodes"."value" = 1 AND "seconds_edges"."value" = 2

【讨论】:

您可能知道,如何根据其中一列建立排序?【参考方案2】:

当然,您可以为关系使用表别名(可能是从 rails 5 开始的),如下所示:

def Edge < ActiveRecord::Base
    ...
    def self.joins_alias
        # Generate something like 
       join_name = table.table_alias || table.name
       table_to_join = ... # table name to join
       alias_to_join = ... # table alias to join
       joins("INNER JOIN #table_to_join as #alias_to_join ON #alias_to_join.external_id = #join_name.id")
    end
end

【讨论】:

以上是关于Rails 使用别名查询连接关联表的主要内容,如果未能解决你的问题,请参考以下文章

TypeORM 无关联关系的mysql多表连接查询

Rails 4 - 如何在活动记录查询中为包含()和连接()提供别名

mysql多个表之间的连接方式(内连接左连接右连接)delete删除表内数据的方法以及mysql索引

Rails HABTM 关联:记录未插入连接表

连接查询与子查询

sql查询语句学习,多表查询和子查询以及连接查询