我正在使用SELECT DISTINCT
并且在尝试按相关值排序结果时出现问题。以这个例子(在Rails中):
我的Cook
模型具有明显的customers
关联:
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"
这很好用! (orders
表通过meals
关联,但可以随意忽略)
我想按照这些客户的订单的最新created_at
值来订购此客户列表。但是当我这样做时,我收到一个错误:
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...
即使我明确地加入了表格(因为has_many through
而不认为我应该这样做),这仍然无效。
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_by
),因为我计划将其他查询链接到此。
谢谢:)
答案 0 :(得分:0)
你为什么要这样做呢
has_many :customers, -> { distinct }, through: :orders, source: :user
我可以让不同的客户使用它 cook.rb
class Cook < ActiveRecord::Base
has_many :orders
has_many :customers, through: :orders
end
cook = Cook.first
Customer.joins(:orders).joins(:cooks).where('"orders_customers_join"."cook_id" = ?', saad.id).distinct.to_sql
这会给你以下结果
"SELECT DISTINCT \"customers\".* FROM \"customers\" INNER JOIN \"orders\" ON \"orders\".\"customer_id\" = \"customers\".\"id\" INNER JOIN \"orders\" \"orders_customers_join\" ON \"orders_customers_join\".\"customer_id\" = \"customers\".\"id\" INNER JOIN \"cooks\" ON \"cooks\".\"id\" = \"orders_customers_join\".\"cook_id\" WHERE (\"orders_customers_join\".\"cook_id\" = 1)"
现在这将给我所有不同的客户。
答案 1 :(得分:0)
您不必手动指定加入条件,您可以使用includes
来执行此操作,ActiveRecord将负责加入条件。
cook.customers.includes(:orders).order('orders.created_at DESC').references(:orders).to_sql
答案 2 :(得分:0)
对我来说这很有用。我的模型Apartment.rb有默认的范围排序。
这不起作用
has many :apartments
has_many :buildings, -> {distinct}, through: :apartments
这样做
has many :apartments
has_many :buildings, through: :apartments
def buildings
super.uniq
end