Find_by_sql作为Rails范围

时间:2014-08-22 19:55:29

标签: sql ruby-on-rails chaining scopes

来自Sitepoint的r937非常友好,可以帮助我找出从数据库中返回正确结果所需的查询。

我需要的是能够将此查询用作范围,并能够将其他范围链接到此范围。

查询是:

SELECT coasters.*
FROM (
    SELECT order_ridden,
           MAX(version) AS max_version
    FROM coasters
    GROUP BY order_ridden
) AS m
INNER JOIN coasters
ON coasters.order_ridden = m.order_ridden
AND COALESCE(coasters.version,0) = COALESCE(m.max_version,0)

我尝试制作这样的范围:

  scope :uniques, lambda {
    find_by_sql('SELECT coasters.*
                 FROM (
                   SELECT order_ridden,
                          MAX(version) AS max_version
                   FROM coasters
                   GROUP BY order_ridden
                 ) AS m
                 INNER JOIN coasters
                 ON coasters.order_ridden = m.order_ridden
                 AND COALESCE(coasters.version,0) = COALESCE(m.max_version,0)')
  }

但是当我尝试将另一个示波器链接到它上面时,它失败了。有没有办法像普通范围一样运行此查询?

1 个答案:

答案 0 :(得分:14)

find_by_sql会返回Array。但是你需要一个ActiveRecord::Relation来链接其他范围。

使用将返回ActiveRecord::Relation的ActiveRecord方法重写查询的一种方法是重新排列它,以便嵌套发生在INNER JOIN部分。

您可能想要尝试以下内容:

scope :uniques, lambda {
  max_rows = select("order_ridden, MAX(version) AS max_version").group(:order_ridden)
  joins("INNER JOIN (#{max_rows.to_sql}) AS m
    ON coasters.order_ridden = m.order_ridden
   AND COALESCE(coasters.version,0) = COALESCE(m.max_version,0)")
}