2017-06-08 9 views
0

カラムの1つの値でユニークな多型オブジェクトを取得しようとしています。私はPostgresを使用しています。Railsで作成された最後のユニークな多相オブジェクトを選択してください

オブジェクトは、次の特性をもつidavailable_typeavailable_idvaluecreated_atupdated_at

available_typeが「ユーザー」のレコードの最新のオブジェクトを(created_atで確定)としたいと考えています。

私はActiveRecordのは、このようなクエリしようとしてきた:

Service.where(available_type: "User").order(created_at: :desc).distinct(:available_id) 

しかし、それはavailable_idごとに一つに限定されるものではありません。左を使用して

答えて

1

私は特定の `available_id`を必要としない

Service.where(id: Service 
       .where(available_type: "User") 
       .group(:available_id) 
       .maximum(:id).values) 
+0

ありがとうございました。このソリューションはどのように優れていますか? – Andrew

+0

レコードの数に関係なく、任意の時点で2つの連続したクエリが生成されます。一方、もう1つの解決策は明らかにn + 1 ... –

+0

この解決策は、最新のものを取得していません:created_at。最大の:idのみ。ほとんどの場合、これらは同じものですが、:idと:idを入れ替えようと思っているかもしれません。created_at – TheRealMrCrowley

1

は、次のSQLの方が大きいのcreated_atと行がない行のみを選択して、あなたのおそらく最も効率的な方法

になるだろうに参加します。

詳細はこの記事を参照してください:https://stackoverflow.com/a/27802817/5301717

query = <<-SQL 
    SELECT m.*     # get the row that contains the max value 
    FROM services m     # "m" from "max" 
    LEFT JOIN services b  # "b" from "bigger" 
     ON m.available_id = b.available_id # match "max" row with "bigger" row by `home` 
     AND m.available_type = b.available_type 
     AND m.created_at < b.created_at # want "bigger" than "max" 
    WHERE b.created_at IS NULL  # keep only if there is no bigger than max 
    AND service.available_type = 'User' 
SQL 

Service.find_by_sql(query) 

明瞭には、引数として偽/唯一の真の列名を取りません。

distinctは、別個のレコードのみを返すためのもので、特定の値のフィルタリングとは関係ありません。

あなたが特定のavailable_idが必要な場合、あなたはwhere

例えばを使用する必要があります最初の異なる多型の値を取得するループ

が必要になりますだけでは、各個別のavailable_idの最新を取得する必要がある場合は、最新のlimit

Service.distinct.where(available_type: "User").where(available_id: YOUR_ID_HERE).order(created_at: :desc).limit(1) 

を追加取得するには

Service.distinct.where(available_type: "User").where(available_id: YOUR_ID_HERE).order(created_at: :desc) 

、区別する必要がある列を選択するだけでselect

available_ids = Service.distinct.select(:available_id).where(available_type: 'User') 

は、各IDの最新のを取得:

recents = [] 
available_ids.each do |id| 
    recents << Service.where(available_id: id).where(available_type: 'User').order(created_at: :desc).limit(1) 
end 
+0

を試してみて、私は一握りがある(available_id''ごとに1つの結果を必要としますあなたの照会列 – Andrew

+0

は' .where(available_idでしょう:YOUR_ID_HERE) 'あなたはまだ使用されてきましたか?私は1つの 'available_id'のための結果を必要としません、私はそれぞれの' available_id'のために1つの結果を望みます。 – TheRealMrCrowley

+0

を制限する必要があります。その場合には 'available_ids') – Andrew

関連する問題