2017-04-25 46 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)