【问题标题】:Rails LEFT OUTER JOIN with SubqueryRails LEFT OUTER JOIN 与子查询
【发布时间】:2015-04-04 10:09:35
【问题描述】:

我有一个简单的日历应用程序。

型号:

class Day < ActiveRecord::Base
  self.primary_key = "sdate"
  has_many :items, foreign_key: :sdate
end

class Item < ActiveRecord::Base
  belongs_to :day, :foreign_key => :sdate
  belongs_to :calendar
end

class Calendar < ActiveRecord::Base
  has_many :items
end

要求: 获取特定日期范围内的所有天数行。 获取具有特定 Calendar-ID 的相关项目行。

使用 SQL 我可以使用以下查询:

SELECT * FROM days LEFT OUTER JOIN (
  SELECT * FROM items
  WHERE calendar_id IN (1, 4)
) AS items
ON days.sdate = items.sdate
WHERE days.sdate BETWEEN '2015-03-01' AND '2015-03-31';

我在 Rails 中尝试了多种方法,但找不到解决方案。

如何在 Rails 4 中做到这一点?渴望加载会很棒。

【问题讨论】:

  • 听起来像是两个不同的要求,是吗?

标签: ruby-on-rails activerecord subquery


【解决方案1】:

我只是想弄清楚这一点,但我不知道有什么方法可以用纯 Rails 做到这一点。但这会做你想做的事:

Day.joins("LEFT OUTER JOIN (
  SELECT * FROM items
    WHERE calendar_id IN (1, 4)
  ) AS items
  ON days.sdate = items.sdate
  WHERE days.sdate BETWEEN '2015-03-01' AND '2015-03-31'");

我没有在我的代码中的查询中使用日期,所以我不确定您是否需要在日期周围加上单引号。但这就是语法。我认为左连接非常方便,我希望 Rails 有一个实际的左连接方法。

【讨论】:

  • 谢谢Beartech!今天晚些时候我会试试的。
  • 抱歉迟到了!我会在接下来的两天内尝试一下。
  • 该解决方案有效。但不幸的是,在访问项目时,它会产生大量额外的数据库查询。
  • 我在 Rails 中看到了很多。或者至少它看起来像很多查询,因为 Rails 不会做很多急切的加载。您在这里得到一个 ActiveRecord::Relation,而不仅仅是查询的结果。如果您担心数据库查询,那么正确的做法是使用此查询创建数据库视图。复杂查询是数据库的领域,这也是数据库的设计目的。如果您基本上希望一个临时表在一次调用中一次查看所有这些查询,那么数据库视图是您的最佳选择。除非出现更好的答案,否则我会很感激它被标记为正确答案。
  • 感谢您推荐数据库视图!使用视图可能是一个合适的解决方案。
【解决方案2】:

类似的东西:

Day.joins('LEFT OUTER JOIN items ON days.sdate = items.sdate')
     .where('items.calendar_id IN (1, 4)')
     .where('days.sdate' => start_time..end_time)

http://guides.rubyonrails.org/active_record_querying.html

【讨论】:

  • 感谢您的建议!不幸的是,有一个问题:如果某一天只有一个 calendar_id 为 3 的项目,那么这一天将在结果中丢失。
  • 另一个问题:没有物品的日子也丢失了。
  • 尝试在控制台中使用.to_sql 运行它并调整它以生成您想要的查询。
  • Relation#to_sql 返回一条 SQL 语句。但我已经有一条 SQL 语句。所以我不明白我为什么要这样做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-10
  • 2014-07-14
  • 2013-03-14
  • 1970-01-01
  • 1970-01-01
  • 2010-09-29
相关资源
最近更新 更多