ruby-on-rails-3 - Ruby on Rails - 如何连接两个表?

标签 ruby-on-rails-3 join active-relation

我有两个一对多关系的表(主题和页面)。我想从主题和页面中添加条件来解析 sql,但进展非常缓慢,而且经常遇到问题。我是 Rails 的新手,请帮忙。

class Subject < ActiveRecord::Base
  has_many :pages
end

class Page < ActiveRecord::Base
  belongs_to :subject 
end

主题中的示例数据,下面列出了三列:

id  name    level
1   'Math'  1
6   'Math'  2
...

页面中的示例数据,列如下:

id  name                    subject_id
--  --------------------    ----------
2   Addition                1
4   Subtraction             1
5   Simple Multiplication   6
6   Simple Division         6
7   Hard Multiplication     6
8   Hard Division           6
9   Elementary Divsion      1

鉴于我不知道subject.id,我只知道主题名称和级别,以及页面名称。这是我要生成的 sql(或可以达到相同结果的类似语句):

select subjects.id, subjects.name, pages.id, pages.name from subjects, pages
 where subjects.id = pages.subject_id
   and subjects.name = 'Math'
   and subjects.level = '2'
   and pages.name like '%Division'  ;

我希望在结果中得到两行:

subjects.id     subjects.name   pages.id    pages.name 
-----------     -------------   --------    -----------
6               Math            6           Simple Division
6               Math            8           Hard Division

这是一个非常简单的sql,但是我一直没能在rails中得到我想要的。

Here is my rails console:  

>> subject = Subject.where(:name => 'Math', :level => 2)
  Subject Load (0.4ms)  SELECT `subjects`.* FROM `subjects` WHERE `subjects`.`name` = 'Math' AND `subjects`.`level` = 2
[#<Subject id: 6, name: "Math", position: 1, visible: true, created_at: "2011-12-17 04:25:54", updated_at: "2011-12-17 04:25:54", level: 2>]
>> 
>> subject.joins(:pages).where(['pages.name LIKE ?', '%Division'])
  Subject Load (4.2ms)  SELECT `subjects`.* FROM `subjects` INNER JOIN `pages` ON `pages`.`subject_id` = `subjects`.`id` WHERE `subjects`.`name` = 'Math' AND `subjects`.`level` = 2 AND (pages.name LIKE '%Division')
[#<Subject id: 6, name: "Math", position: 1, visible: true, created_at: "2011-12-17 04:25:54", updated_at: "2011-12-17 04:25:54", level: 2>, #<Subject id: 6, name: "Math", position: 1, visible: true, created_at: "2011-12-17 04:25:54", updated_at: "2011-12-17 04:25:54", level: 2>]
>> 
>> subject.to_sql
"SELECT `subjects`.* FROM `subjects`  WHERE `subjects`.`name` = 'Math' AND `subjects`.`level` = 2"
>> subject.size
1
>> subject.class
ActiveRecord::Relation

第一个语句:subject = Subject.where(:name => 'Math', :level => 2) 第二条语句:subject.joins(:pages).where(['pages.name LIKE ?', '%Division'])

问题:

  1. 链式 sql 的结果确实返回了两行,但是 subject.size 说只有 1?
  2. 我如何告诉它也从 :pages 返回列?
  3. 为什么 subject.to_sql 仍然只显示来自语句 1 的 sql,为什么它不包括来自语句 2 的链式 sql?
  4. 本质上,我需要怎样编写不同的语句来解析上面列出的 sql(或获得相同的结果)?

非常感谢。

最佳答案

1) ActiveRecord 会将您的查询结果映射到对象,而不是任意返回的行,因此因为您基于它正在查看的Subject 类创建查询您得到的行和计算出它仅引用 1 个唯一的 Subject 对象,因此仅返回单个 Subject 实例。

2) 列数据在那里,但您正在处理 ActiveRecord 想要提供给您的对象,即对象。如果您希望返回页面,则需要将查询的创建基于 Page 类。

3) 您没有将添加 join(:pages)... 的结果保存回 subject 变量。如果你这样做了:

subject = subject.joins(:pages).where(['pages.name LIKE ?', '%Division'])

运行 subject.to_sql 时你会得到完整的查询

4) 要获取页面对象,您可以这样做,请注意,我们将其基于 Page 类:

pages = Page.joins(:subject).where(['subjects.name = ? AND subjects.level = ? AND pages.name LIKE ?', 'Math', 2, '%Division'])

然后从那里访问返回的第一个 Page 对象的主题名称:

pages[0].subject.name

因为您首先进行了连接,所以不会产生另一个 SQL 查询。希望这对您有所帮助!

关于ruby-on-rails-3 - Ruby on Rails - 如何连接两个表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8557835/

相关文章:

php - 带有图表的 Join 语句 Laravel

ruby-on-rails - rails 3.0.3 - ActiveRecord::Relation,未定义的方法错误

ruby-on-rails - ActiveRelation 将如何影响 rails 的 includes() 功能?

ruby-on-rails - ActiveRecord 关联选择包含记录的计数

ruby-on-rails - 如何在不加载环境的情况下访问 Rails 应用程序的路由?

ruby-on-rails-3 - Rails 3-如何处理从数据库获取的数据

join - 如何在 Apache Spark SQL 中执行更新

ruby-on-rails - 如何在 Rails 3 中为 DATETIME 列保存当前日期/时间?

ruby-on-rails - rails : Custom validation message

mysql - 在 MySQL 的 JOIN 上设置 LIMIT