sql - 使用 ID 加入的 Rails 3 Active Record 查询接口(interface)的问题

标签 sql ruby-on-rails-3 postgresql activerecord arel

我一直在使用 Rails 3 Active Record 查询接口(interface)时遇到问题。我有一个查找表 (lookups)、一个主表 (through_references) 和一个名为 through_tables 的通过/连接表。因此,这是我使用 has_many :through 设置的 HABTM 配置。

更新:这里要特别注意的是,当我进行这些连接时,我一直在连接 ID,以提供记录过滤。这似乎不适用于 Active Record 查询接口(interface)。如果您不想看到我辛苦工作的血淋淋的细节,您可以跳到下面查看我的解决方法。

我们还将有一些主要项目(through_references 表)应该能够有查找项目的任意组合,并且能够方便地通过复选框单击相关查找项目。

我已经在 github 上发布了代码. github源码上有很多解释。要查看结果,请转到查找索引页面。请注意,您将需要使用脚手架代码创建记录。

我还在 heroku 上启动并运行了代码, 有更多的解释和例子。

class Lookup < ActiveRecord::Base
  has_many :fk_references
  has_many :through_tables
  has_many :through_references, :through => :through_tables
  attr_accessible :name, :value
end

class ThroughTable < ActiveRecord::Base
  belongs_to :through_reference
  belongs_to :lookup
  attr_accessible :description, :through_reference_id, :lookup_id
end

class ThroughReference < ActiveRecord::Base
  has_many :through_tables
  has_many :lookups, :through => :through_tables
  attr_accessible :description
end

如果我们想要列出所有查找项以及与它们对应的主要项,我们可以将“查找”表与主要项 (through_references) 表左联接。 对应的SQL:

SELECT * FROM lookups
  LEFT OUTER JOIN through_tables ON (lookups.id = through_tables.lookup_id AND through_tables.through_reference_id = 1)
  LEFT OUTER JOIN through_references ON through_references.id = through_tables.through_reference_id
  ORDER BY lookups.id

返回记录:

1;“Lookup Item 1”;“1”;“2012-06-06 17:14:40.819791”;“2012-06-06 17:14:40.819791”;1;1;1;“Main Item 1 has Lookup item 1”;“2012-06-06 17:17:31.355425”;“2012-06-06 17:17:31.355425”;1;“Main Item 1”;“2012-06-06 17:16:30.004375”;“2012-06-06 17:16:30.004375”

2;“Lookup Item 2”;“2”;“2012-06-06 17:14:59.584756”;“2012-06-06 17:14:59.584756”;;;;“”;“”;“”;;“”;“”;“”

3;“Lookup Item 3”;“3”;“2012-06-06 17:15:14.700239”;“2012-06-06 17:15:14.700239”;2;1;3;“Main Item 1 has Lookup item 3”;“2012-06-06 17:17:53.169715”;“2012-06-06 17:17:53.169715”;1;“Main Item 1”;“2012-06-06 17:16:30.004375”;“2012-06-06 17:16:30.004375”

这是我所期望的。

=== 使用自定义左连接的 Active Record 查询接口(interface)

Lookup.joins(“LEFT OUTER JOIN through_tables ON (lookups.id = through_tables.lookup_id AND through_tables.through_reference_id = 1)” ).includes(:through_references).order(‘lookups.id’)

从 Active Record 查询接口(interface)返回的内容(注意我在 Active Record 层次结构中向下导航):

Lookup ID Lookup Name Lookup Value Through Table ID Through Table Description Main Item ID Main Item Description
1 Lookup Item 1 1 1 Main Item 1 has Lookup item 1 1 Main Item 1
1 Lookup Item 1 1 3 Main Item 2 has Lookup item 1 2 Main Item 2
2 Lookup Item 2 2 4 Main Item 2 has Lookup item 2 2 Main Item 2
3 Lookup Item 3 3 2 Main Item 1 has Lookup item 3 1 Main Item 1

这不是我所期望的。

我们这里的内容与简单的左连接相同(没有 AND 子句)。这告诉我 AND 子句在 Active Record 查询接口(interface)中被忽略了。

=== 使用 find_by_sql 方法的 Active Record 查询接口(interface)

Lookup.find_by_sql("SELECT * FROM lookups LEFT OUTER JOIN through_tables ON (through_tables.lookup_id = lookups.id AND through_tables.through_reference_id = 1) LEFT OUTER JOIN through_references ON through_references.id = through_tables.through_reference_id ORDER BY lookups.value, through_references.id" )

从 Active Record 查询接口(interface)返回的内容(注意我在 Active Record 层次结构中向下导航):

Lookup ID   Lookup Name     Lookup Value    Through Table ID    Through Table Description   Main Item ID    Main Item Description
1   Lookup Item 1   1   3   Main Item 2 has Lookup item 1   2   Main Item 2
1   Lookup Item 1   1   1   Main Item 1 has Lookup item 1   1   Main Item 1
    Lookup Item 2   2   No through_tables entry
1   Lookup Item 3   3   3   Main Item 2 has Lookup item 1   2   Main Item 2
1   Lookup Item 3   3   1   Main Item 1 has Lookup item 1   1   Main Item 1

这里的结果很疯狂!

这是一个 BUG,这是预期的效果,还是我遗漏了什么?

我希望有一种简洁的方法来执行此操作,而不必生成两个结果集并通过代码合并它们。

最佳答案

我找到了解决方法。问题似乎是 Active Record 无法识别对 ID 进行过滤的联接(LEFT OUTER JOIN xyz ON xyz.id = ID)。

我的解决方法是创建一个将 ID 作为参数的存储过程或函数,在数据库中进行连接,并返回一个漂亮的平面记录集。

参见:Heroku demo page (skip to bottom)

请注意,我没有将此标记为解决方案,因为这是一种变通方法,与事件记录无关。

关于sql - 使用 ID 加入的 Rails 3 Active Record 查询接口(interface)的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10936985/

相关文章:

sql - 使用 AND 和 OR 通过查询检索多行

mysql - 获取具有连接的人员的事件任务

SQL查询: SUM values up to the current record

ruby-on-rails - ruby on Rails : Rails. cache.write 对于特定对象字段数组返回 false

php - 使用 PostgreSQL 以简单的方式获取所有父项

SQL 日期格式转换为 MMDDYYYY

ruby-on-rails - Rails 控制台给我一个 "wirble"错误

ruby-on-rails-3 - 如何从通过 HTTP Post 收到的电子邮件中获取 header 信息(例如主题)

java - 如何以编程方式在 Java 中使用渗透导入 OSM 数据?

java - postgres 和 java 的内存缓存选项