Rails 2.3.8:如何根据字段的最高值选择记录?

时间:2010-11-23 10:50:55

标签: ruby-on-rails ruby-on-rails-3

我正在回复几天前提出的问题。click this看到上一个问题

我已回答了这个问题。但这不正确。

表中的记录

alt text

Revision.find(:all,:select => "id,name,max(revision) as revision", :conditions => ["saved=1"],:group => 'name')

会导致

alt text

实际上结果应该是id 3,6,8。

查询中的哪些修改会导致此结果?

4 个答案:

答案 0 :(得分:1)

这是SQL不适合的查询类型。简而言之,问题在于您实际需要的是一个组操作,然后在每个组中进行排序,然后从每个子组中获取最高记录。事实证明这是一个令人惊讶的难题,因为SQL在排序之前会进行分组。通常,分组用于汇总数据,而不是选择特定记录。

有许多特定于SQL的方法可以解决这个问题,但是它们都不适合Rails。相反,我会像这样构建你的数据:

  1. 拥有recipe_revisions模型,其中包含完整的食谱记录
  2. 有一个食谱模型,基本上只是id / name / latest revision。
  3. 要获取配方的当前副本,您将从配方中选择所需的配方,然后在name / max revision上连接到recipe_revisions,其中这些列在两个表上都被编入索引。
  4. 这不是一个简单的解决方案,它会很好用。

答案 1 :(得分:0)

将您的查询拆分为两个。在第一个中找到每个名称的最大修订版本。在第二个查询中,找到与name和revision匹配的完整行。

CREATE TEMP TABLE max_revisions (name varchar, revision integer);
INSERT INTO max_revisions SELECT name, max(revision) FROM revisions
       WHERE saved = 1 GROUP BY name;
SELECT r.* FROM revisions r INNER JOIN max_revisions m
       ON m.name = r.name AND m.revision = r.revision;

现在您的问题可能是,如何在Rails中表达这一点。

您可以使用Revision.connection.execute然后使用Revision.find_by_sql(两者都包含在单个方法中,例如:Revision.find_by_max_revisions)。

否则,如果您的数据库不支持临时表,或者您只是不想要它们,您可以将max_revisions读入内存,然后使用它来构建查询:

class Revision
  def self.find_by_max_revisions
    max_revs = connection.select_values(
      sanitize_sql(
        ["SELECT name, max(revision) as max_rev FROM #{table_name}
               WHERE saved = ? GROUP BY name", 1]
      ), "Load max_revisions for #{self.name}"
    )
    max_revs.map do |row|
      find_by_name_and_revision(row["name"], row["max_rev"].to_i)
    end
  end
end

答案 2 :(得分:0)

Revision.find(:all, :select => "DISTINCT id", :conditions => ["saved=1"], :order => 'revision DESC')

答案 3 :(得分:0)

我遇到了类似的问题,而且我还没有能够将其转换为活动记录语法,但是同事帮我掀起了一个嵌套选择,为我解决了这个问题。像这样:

select id, name, saved, revision
from revisions r
where saved = 1 and
version_no = (select revision 
              from revisions r2
              where saved = 1 and r2.name = r.name
              order by r2.revision desc
              limit 1 
             )

警告:我不确定性能影响,因为我怀疑这是为每个唯一的修订字段进行第二次子查询。