【问题标题】:Not able to select distinct row from each group using ActiveRecord with PostgreSQL in Rails无法在 Rails 中使用 ActiveRecord 和 PostgreSQL 从每个组中选择不同的行
【发布时间】:2015-01-16 15:36:00
【问题描述】:

我的 ActiveRecord 查询有一个小问题。
我有一个 Product 模型,它看起来像:

#<Product id: nil, name: nil, price: nil, order_id: nil, created_at: nil, updated_at: nil, restaurant_id: nil>

现在我想在所有名称上选择 DISTINCT,并取回所有产品的属性。

我试过了:

@products = Product.where(restaurant_id: !nil).group("products.name").order("name")

但我收到了这个错误:

PG::GroupingError: ERROR:  column "products.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT  "products".* FROM "products"  WHERE "products"."rest...
                ^
: SELECT  "products".* FROM "products"  WHERE "products"."restaurant_id" = 1 GROUP BY products.name  

好的,然后我将 product_id 添加到我的查询中:

@products = Product.where(restaurant_id: !nil).group("products.name, products.id").order("name")

但此查询返回名称重复的产品。 所以我也尝试了这个:

@products = Product.where(restaurant_id: !nil).select("DISTINCT(NAME)").order("name")

但作为回报,我只得到了带有 id 和 name 的 Product 记录(很明显),所以如果这个查询返回正确的集合,我添加了稍后需要的属性:

@products = Product.where(restaurant_id: !nil).select("DISTINCT(NAME), restaurant_id, price").order("name")

它还会返回重复的名称。

您有什么解决方案或想法,如何为 PostgreSQL 修复此查询?
我习惯于写这样的查询(在 MySQL 上),这是正确的:

@products = Product.where(restaurant_id: !nil).select("DISTINCT(NAME), restaurant_id, price").order("name")

为什么 PostreSQL 不接受该查询?

【问题讨论】:

  • 试试这个Product.where.not(restaurant_id: nil).select("DISTINCT ON(name) name, restaurant_id, price, updated_at").order("name, updated_at")。阅读SELECT DISTINCT ON ( expression [, ...] ) 只保留给定表达式计算结果为等于的每组行的第一行......
  • 请告诉我结果。我无法尝试,因为我没有准备好数据的表格。所以我需要你的确认..)

标签: ruby-on-rails ruby postgresql ruby-on-rails-4 activerecord


【解决方案1】:

你应该把查询写成:-

Product.where
       .not(restaurant_id: nil)
       .select("DISTINCT ON(name) name, restaurant_id, price, updated_at")
       .order("updated_at, name")

根据官方文档SELECT DISTINCT ON ( expression [, ...] )

只保留给定表达式计算结果为相等的每组行的第一行。 DISTINCT ON 表达式使用与 ORDER BY 相同的规则进行解释(见上文)。 请注意,除非使用ORDER BY 确保所需的行首先出现,否则每组的“第一行”是不可预测的。例如:

SELECT DISTINCT ON (location) location, time, report
FROM weather_reports
ORDER BY location, time DESC;

检索每个位置的最新天气报告。但是,如果我们没有使用ORDER BY 来强制每个位置的时间值降序排列,我们就会从每个位置的不可预测时间得到一个报告。

【讨论】:

  • 我认为以下内容也适用于 OP 的目的:Product.where(condition).group(:name).select(Product.column_names.join(',')) Beats 编写 SQL IMO。 (可能不需要join
猜你喜欢
  • 2012-10-24
  • 1970-01-01
  • 2015-11-24
  • 2019-09-11
  • 1970-01-01
  • 2022-01-07
  • 2017-02-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多