2017-04-25 45 views
3

标题道歉,因为我不知道如何简洁地描述我的问题。ActiveRecord根据自定义唯一性和最大列值进行选择

我们假设我们在数据库中有多个Item实例,并包含以下列:name,yearversion。下面的示例:

| id | name  | year | version | 
|----|-----------|--------|---------| 
| 1 | Blockhead | 2010 | 1  | 
| 2 | Blockhead | 2010 | 2  | 
| 3 | Jughead | 2011 | 1  | 

我只想返回结果其中名字和年份是唯一的,但只返回最新版本的名称/年的独特组合。即,我想回到:

| id | name  | year | version | 
|----|-----------|--------|---------| 
| 2 | Blockhead | 2010 | 2  | 
| 3 | Jughead | 2011 | 1  | 

如果可能的话,我想没有一个分组数据集...但我的SQL知识/ AR在这方面是有限的,我不知道是什么正确的解决方案将是。我目前检索所有记录,然后筛选出我不想要的记录,但这是一个不合理的解决方案。

@items = ::Item.active.paginate(per_page: 30, page: page || 1).to_a 

# Do not show a given item unless it's the latest version 
@items.delete_if do |item| 
    @items.any? do |other| 
    other.id != item.id && 
     other.read_attribute(:name) == item.read_attribute(:name) && 
     other.year == item.year && 
     other.version > item.version 
    end 
end 

回答

0

看看相关的SO问题:Retrieving the last record in each group

你的情况选择最简单的查询所需的数据将是:

SELECT name, year, MAX(version) as version 
FROM items 
GROUP BY name, year; 

如果要选择其他列(id为例如)或为了避免分组结果,你可以用子查询来做:

SELECT * FROM items 
WHERE id IN (
    SELECT MAX(id) 
    FROM items 
    GROUP BY name, year); 

此代码假定MAX(id)给出该行中最新的version行中的id。此查询

Rails代码:

sub_query = Item.select("MAX(id)").group(:name, year).to_sql 
Items.where("id iN (?)", subquery)