select 在 Rails 中使用 ActiveRecord 和 PostgreSQL 无法区分每个组的行
Not able to select distinct row from each group using ActiveRecord with PostgreSQL in Rails
我的 ActiveRecord 查询有一个小问题。
我有一个产品模型,它看起来像:
#<Product id: nil, name: nil, price: nil, order_id: nil, created_at: nil, updated_at: nil, restaurant_id: nil>
现在我想 select 区分所有名称,并取回所有产品的属性。
我试过了:
@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")
但此查询 returns 产品具有重名。
所以我也尝试了这个:
@products = Product.where(restaurant_id: !nil).select("DISTINCT(NAME)").order("name")
但在 return 中我只得到了只有 ID 和名称的产品记录(很明显),所以如果这个查询 return 设置正确,我添加了我稍后需要的属性:
@products = Product.where(restaurant_id: !nil).select("DISTINCT(NAME), restaurant_id, price").order("name")
而且return也是重名。
您有任何解决方案或想法,如何解决 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("updated_at, name")
根据官方文档SELECT DISTINCT ON ( expression [, ...] )
keeps only the first row of each set of rows where the given expressions evaluate to equal. The DISTINCT ON
expressions are interpreted using the same rules as for ORDER BY
(see above). Note that the "first row" of each set is unpredictable unless ORDER BY
is used to ensure that the desired row appears first. For example:
SELECT DISTINCT ON (location) location, time, report
FROM weather_reports
ORDER BY location, time DESC;
retrieves the most recent weather report for each location. But if we had not used ORDER BY
to force descending order of time values for each location, we'd have gotten a report from an unpredictable time for each location.
我的 ActiveRecord 查询有一个小问题。
我有一个产品模型,它看起来像:
#<Product id: nil, name: nil, price: nil, order_id: nil, created_at: nil, updated_at: nil, restaurant_id: nil>
现在我想 select 区分所有名称,并取回所有产品的属性。
我试过了:
@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")
但此查询 returns 产品具有重名。 所以我也尝试了这个:
@products = Product.where(restaurant_id: !nil).select("DISTINCT(NAME)").order("name")
但在 return 中我只得到了只有 ID 和名称的产品记录(很明显),所以如果这个查询 return 设置正确,我添加了我稍后需要的属性:
@products = Product.where(restaurant_id: !nil).select("DISTINCT(NAME), restaurant_id, price").order("name")
而且return也是重名。
您有任何解决方案或想法,如何解决 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("updated_at, name")
根据官方文档SELECT DISTINCT ON ( expression [, ...] )
keeps only the first row of each set of rows where the given expressions evaluate to equal. The
DISTINCT ON
expressions are interpreted using the same rules as forORDER BY
(see above). Note that the "first row" of each set is unpredictable unlessORDER BY
is used to ensure that the desired row appears first. For example:
SELECT DISTINCT ON (location) location, time, report
FROM weather_reports
ORDER BY location, time DESC;
retrieves the most recent weather report for each location. But if we had not used
ORDER BY
to force descending order of time values for each location, we'd have gotten a report from an unpredictable time for each location.