【问题标题】:ActiveRecord select based on custom uniqueness and maximum column value基于自定义唯一性和最大列值的 ActiveRecord 选择
【发布时间】:2017-04-25 19:28:38
【问题描述】:

抱歉标题,因为我不知道如何简洁地描述我的问题。

假设我们在数据库中有多个 Item 实例,其中包含以下列:nameyearversion。示例如下:

| 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

【问题讨论】:

    标签: mysql sql ruby-on-rails activerecord


    【解决方案1】:

    查看相关的 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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-25
      • 2019-11-19
      • 1970-01-01
      • 1970-01-01
      • 2017-02-18
      相关资源
      最近更新 更多