2017-05-02 9 views
0

すべての顧客を最新の注文日(さらにページ番号付け)と共にリストする必要があります。アクティブレコード - 2番目のテーブルでネストされた選択を実行する方法?

アクティブレコードを使用して次のSQLクエリを作成するにはどうすればよいですか?

select *, 
    (
    select max(created_at) 
    from orders 
    where orders.customer_id = customers.id 
) as latest_order_date 
from customers 
limit 25 offset 0 

私はこれを試してみましたが、それはmissing FROM-clause entry for table "customers"を文句:

Customer 
    .select('*') 
    .select(
    Order 
     .where('customer_id = customers.id') 
     .maximum(:created_at) 
).page(params[:page]) 

# Generates this (clearly only the Order query): 
SELECT MAX("orders"."created_at") 
FROM "orders" 
WHERE (customer_id = customers.id) 

はEDIT:ARのパラメータ化とkaminariのページネーションの良さを保つために良いでしょう。

+0

[ActiveRecordのネストされたSELECT](http:// stackoverflow。com/questions/37377455/activerecord-nested-select) – Iceman

+0

ありがとう、私は可能な重複をチェックしましたが、それは少し異なります。彼らは単一のテーブルから選択します。ここでは、2つのテーブルから選択します。だから、そこの答えはこの問題を解決しません。 –

答えて

0

私がこれまでに作ってみたほとんどのActive Recordっぽい方法は次のとおりです。

Customer 
    .page(params[:page]) 
    .select('*') 
    .select(<<-SQL.squish) 
    (
     SELECT MAX(created_at) AS latest_order_date 
     FROM orders 
     WHERE orders.customer_id = customers.id 
    ) 
    SQL 

私はまだ私は、文字列の一部で、よりアクティブレコードっぽいを作ることができることを望みます。

<<-SQLは、ちょうどheredocです。

0

この2つのテーブルの関係についての情報はまだありませんので、Customerhas_manyOrdersとします。

ActiveRecordはあなたがしようとしているものをサポートしていませんが、それはArelの上に構築されます。

すべてのRailsモデルにはarel_tableというメソッドがあり、対応するArel::Tableが返されます。デフォルトの方法が少し面倒なので、a helper libraryでこのクリーナーを作成することをお勧めします。私は互換性を最大限にするためにプレーンなArel構文を使用します。

ActiveRecordはArelオブジェクトを認識し、独自の構文の横にそれらを受け入れることができます。これは、これを行うための通常の方法ですが、あなたはまだサブクエリとしてそれをしたい場合は、あなたが与えるこの

Customer.select([ 
    customers[Arel.star], 
    orders.project(orders[:created_at].maximum) 
     .where(orders[:customer_id].eq(customers[:id])) 
     .as('latest_order_date') 
]) 

を行うことができます

SELECT "customers".*, MAX("orders"."created_at") AS "latest_order_date" 
FROM "customers" 
INNER JOIN "orders" ON "orders"."customer_id" = "customers"."id" 
GROUP BY "customers"."id" 

を生成

orders = Order.arel_table 
customers = Customer.arel_table 

Customer.joins(:orders).group(:id).select([ 
    customers[Arel.star], 
    orders[:created_at].maximum.as('latest_order_date') 
]) 

私たち

SELECT "customers".*, (
    SELECT MAX("orders"."created_at") 
    FROM "orders" 
    WHERE "orders"."customer_id" = "customers"."id") "latest_order_date" 
FROM "customers" 
+0

GROUP BY – Rob

+0

@Robのない集合関数を使用しているので、INNER JOINクエリは実行されません。 –

0

彼女eは@adamが与えていたのと同じ回答ですが、ARELとまっすぐActiveRecordを使用していません。わからないことは、OPは言いませんが、クエリにはない、本当にジョアン・マルセロ・ソウザ

Customer.select("customers.*, max(orders.created_at)").joins(:orders).group("customers.id").page(params[:page]) 

(ことを回避することにより、グループがthis feature of Postgres 9.1 and higherを使用して、すべての顧客の列をリストします。)

@よりもはるかにましです顧客が発注していないケースを処理します。このバージョンでは、次の処理が行われます。

Customer.select("customers.*, coalesce(max(orders.created_at),0)").joins("left outer join orders on orders.customer_id=customers.id").group("customers.id").page(params[:page]) 
関連する問題