Sql 从“has_many”到-gt;{distinct}`由关联的值执行

Sql 从“has_many”到-gt;{distinct}`由关联的值执行,sql,ruby-on-rails,postgresql,activerecord,Sql,Ruby On Rails,Postgresql,Activerecord,我正在使用一个SELECT DISTINCT,试图按关联值对结果排序时出现问题。以这个例子(在Rails中): 我有一个Cook模型,它与客户有着明显的关联: has_many :customers, -> { distinct }, through: :orders, source: :user 这很明显,因为我只想统计一次客户,即使他们有多个订单 为此生成的SQL为: > cook.customers.to_sql => "SELECT DISTINCT \"users\

我正在使用一个
SELECT DISTINCT
,试图按关联值对结果排序时出现问题。以这个例子(在Rails中):

我有一个
Cook
模型,它与
客户有着明显的关联:

has_many :customers, -> { distinct }, through: :orders, source: :user
这很明显,因为我只想统计一次客户,即使他们有多个订单

为此生成的SQL为:

> cook.customers.to_sql
=> "SELECT DISTINCT \"users\".* FROM \"users\"
 INNER JOIN \"orders\" ON \"users\".\"id\" = \"orders\".\"user_id\"
 INNER JOIN \"meals\" ON \"orders\".\"meal_id\" = \"meals\".\"id\"
 WHERE \"meals\".\"cook_id\" = 1"
这个很好用!(通过
膳食关联
订单
表,但可以忽略)

我想根据这些客户订单的
价值创建的最新的
来订购此客户列表。但当我这样做时,我会得到一个错误:

cook.customers.order('orders.created_at DESC').to_sql
=> "SELECT DISTINCT \"users\".* FROM \"users\"
    INNER JOIN \"orders\" ON \"users\".\"id\" = \"orders\".\"user_id\"
    INNER JOIN \"meals\" ON \"orders\".\"meal_id\" = \"meals\".\"id        \"WHERE \"meals\".\"cook_id\" = 1  ORDER BY orders.created_at DESC"
  > cook.customers.order('orders.created_at DESC')
  ActiveRecord::StatementInvalid: PG::InvalidColumnReference: ERROR:  for SELECT DISTINCT, ORDER BY expressions must appear in select list
  LINE 1: ...eals"."id" WHERE "meals"."cook_id" = $1  ORDER BY orders.cre...
即使我显式地加入了表(因为
有很多到
),这仍然不起作用

cook.customers.joins(:orders).order('orders.created_at DESC').to_sql
=> "SELECT DISTINCT \"users\".* FROM \"users\" INNER JOIN \"orders\" \"orders_users\" ON \"orders_users\".\"user_id\" = \"users\".\"id\" INNER JOIN \"orders\" ON \"users\".\"id\" = \"orders\".\"user_id\" INNER JOIN \"meals\" ON \"orders\".\"meal_id\" = \"meals\".\"id\" WHERE \"meals\".\"cook_id\" = 1  ORDER BY orders.created_at DESC"
有什么线索吗?我正在寻找一个将返回ActiveRecord关系的解决方案(因此不要使用
sort\u by
),因为我计划将其他查询链接到该关系


谢谢:)

您不必手动指定连接条件,您可以通过使用
includes
来完成,ActiveRecord将处理连接条件

cook.customers.includes(:orders).order('orders.created_at DESC').references(:orders).to_sql

您不必手动指定联接条件,您可以使用
includes
来指定联接条件,ActiveRecord将处理联接条件

cook.customers.includes(:orders).order('orders.created_at DESC').references(:orders).to_sql

对我来说,这很有效。My model Apartment.rb具有默认范围排序

这不管用

has many :apartments
has_many :buildings, -> {distinct}, through: :apartments
确实如此

has many :apartments
has_many :buildings, through: :apartments

def buildings
  super.uniq
end

对我来说,这很有效。My model Apartment.rb具有默认范围排序

这不管用

has many :apartments
has_many :buildings, -> {distinct}, through: :apartments
确实如此

has many :apartments
has_many :buildings, through: :apartments

def buildings
  super.uniq
end

这实际上会产生与我之前得到的错误相同的错误:
ActiveRecord::StatementInvalid:PG::InvalidColumnReference:error:for SELECT DISTINCT,ORDER BY表达式必须出现在select列表中。这实际上会产生与我之前遇到的相同错误:
ActiveRecord::StatementInvalid:PG::InvalidColumnReference:error:对于select DISTINCT,ORDER BY表达式必须出现在选择列表中。使用
.uniq
将对象从ActiveRecord\u关系更改为数组。这可能不太理想,你是对的。在我的例子中,这就足够了,我不需要这些关系,但感谢您指出了这一点。使用
.uniq
将对象从ActiveRecord\u关系更改为数组。这可能不太理想,你是对的。就我而言,这就足够了,我不需要这些关系,但谢谢你指出这一点。