0

次のモデルがあるとします。

User
    id
UserPulses
    id, user_id, group_id, created_at

私がやりたいことは、(group_id) でグループ化されたユーザーの UserPulse をすべて取得し、group_id ごとに最新の UserPulse のみを取得することです。グループごとにループすることでこれを行うことができましたが、それには多数のクエリが必要です。これは1つのクエリで可能ですか?

次のようなもの: user.user_pulses.group("group_id)")

何か案は?ありがとう

4

3 に答える 3

2

通常の ActiveRecord インターフェイスでは確実にこれを行うことはできませんが、ウィンドウ関数を使用して SQL を通じて行うことができます。次のような SQL が必要です。

select id, user_id, group_id, created_at
from (
    select id, user_id, group_id, created_at, 
           row_number() over (partition by group_id order by created_at desc, id desc) as r
    from user_pulses
    where user_id = :user_id
) dt
where r = 1

そしてそれをラップしfind_by_sqlます:

pulses = UserPulses.find_by_sql([%q{
    select id, user_id, group_id, created_at
    from (
        select id, user_id, group_id, created_at, 
               row_number() over (partition by group_id order by created_at desc, id desc) as r
        from user_pulses
        where user_id = :user_id
    ) dt
    where r = 1
}, :user_id => user.id])

ウィンドウ関数部分は基本的に、各 でローカルの GROUP BY を実行しgroup_id、それらを並べ替え ( id desc「念のため」のタイ ブレーカーとして 2 番目の並べ替えキーとして)、グループごとの行番号を に追加しrます。次に、外側のクエリは、各グループ ( where r = 1) and peels off the originaluser_pulses` 列の最初の列を除外します。

于 2012-08-22T02:36:07.333 に答える
2

SQL 機能の PostgreSQL 固有の拡張機能を使用できますDISTINCTDISTINCT ON

SELECT DISTINCT ON (group_id)
       id, user_id, group_id, created_at
FROM   user_pulses
WHERE  user_id = :user_id
ORDER  BY group_id, created_at DESC, id; -- id just to break ties

ウィンドウ関数よりも単純で (移植性はありません)、おそらく最速です。
詳細については、この関連する質問を参照してください

于 2012-08-22T18:15:03.647 に答える
0

このようなもの、おそらく。ただし、同じ日付を共有している場合、user/group_id の組み合わせに対して複数のレコードが存在する可能性があります。

SELECT p.id, p.user_id, p.group_id, p.created_at
  FROM UserPulses p
      ,( SELECT user_id, group_id, MAX(created_at) as max_date
           FROM UserPulses
           GROUP BY user_id, group_id ) m
  WHERE u.user_id = m.user_id
    AND u.group_id = m.group_id
    AND u.created_at = m.max_date
于 2012-08-22T01:51:57.877 に答える