2016-06-17 4 views
0

Ich verwende eine SELECT DISTINCT und habe Probleme beim Versuch, meine Ergebnisse durch einen zugeordneten Wert zu ordnen. Nehmen Sie dieses Beispiel (in Rails):Bestellen von Datensätzen aus `has_many through, -> {distinct}` durch einen zugehörigen Wert

Ich habe ein Cook Modell mit einem deutlichen customers Verein:

has_many :customers, -> { distinct }, through: :orders, source: :user 

Es ist anders, weil ich nur die Kunden wollen einmal zählen, auch wenn sie mehrere Aufträge haben.

Die generierte SQL hierfür ist:

> 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" 

Dies funktioniert gut! (Die orders Tabelle wird durch meals verbunden sind, aber fühlen Sie sich frei zu ignorieren)

Ich möchte diese Liste der Kunden bestellen vom letzten created_at Wert der Aufträge dieser Kunden. Aber wenn ich das tue, bekomme ich einen Fehler:

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... 

Auch wenn ich die Tabellen explizit beitreten (glaube nicht, dass ich wegen has_many through brauchen sollte), ist diese immer noch nicht funktioniert.

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" 

Irgendwelche Hinweise? Ich bin auf der Suche nach einer Lösung, die eine ActiveRecord-Beziehung zurückgibt (also keine Verwendung sort_by), weil ich weitere Anfragen an diese verketten möchte.

Danke :)

Antwort

0

Warum wollen Sie es wie dieser has_many :customers, -> { distinct }, through: :orders, source: :user

ich verschiedene Kunden zu tun haben, mit diesen 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 

und das Sie geben bekommen das folgende Ergebnis

"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)" 

Das wird mir jetzt alle verschiedenen Kunden geben.

+0

Dank ist dies jedoch nicht so optimal, weil ich in der Lage sein mag, dass 'Cook.first.customers' zu nennen (oder ähnlich) und die gewünschten Ergebnisse erhalten, ohne zusätzliche Methoden in meinem Controller anrufen zu müssen. – djfdev

0

Sie müssen die Join-Bedingungen nicht manuell angeben, Sie können dies tun, indem Sie includes10 verwenden und ActiveRecord wird sich um die Join-Bedingungen kümmern.

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

Das ergibt tatsächlich den gleichen Fehler, den ich zuvor bekommen habe: 'ActiveRecord :: StatementInvalid: PG :: InvalidColumnReference: FEHLER: für SELECT DISTINCT müssen ORDER BY Ausdrücke in der Auswahlliste erscheinen'. – djfdev

Verwandte Themen