SQLを少し使って手を汚してもかまわない場合は、ウィンドウ関数 仕事を成し遂げるために。このSQLで投稿IDを取得できます:
select id
from (
select id,
rank() over (partition by thread_id order by created_at desc)
from posts
where receiver_id = #{user.id}
) as dt
where rank = 1
さらに列が必要な場合は、両方のSELECT句に追加します。 #{user.id}
もちろん、あなたが興味を持っている受信者です。
興味深い部分はウィンドウ関数です:
rank() over (partition by thread_id order by created_at desc)
これにより、テーブルがthread_id
に基づいてグループに分割されます。 (ローカライズされたGROUP BYの一種)、タイムスタンプ(最新のものが最初)で並べ替えてから、rank()
各グループの最初のエントリに1、2番目のエントリに2などを生成します。
次のようなテーブルがあるとします。
=> select * from posts;
id | receiver_id | thread_id | created_at
----+-------------+-----------+---------------------
1 | 1 | 2 | 2011-01-01 00:00:00
2 | 1 | 2 | 2011-02-01 00:00:00
3 | 1 | 2 | 2011-03-01 00:00:00
4 | 1 | 3 | 2011-01-01 00:00:00
5 | 1 | 4 | 2011-01-01 00:00:00
6 | 1 | 3 | 2011-01-01 13:00:00
7 | 2 | 11 | 2011-06-06 11:23:42
(7 rows)
内部クエリはこれを提供します:
=> select id, rank() over (partition by thread_id order by created_at desc)
from posts
where receiver_id = 1;
id | rank
----+------
3 | 1
2 | 2
1 | 3
6 | 1
4 | 2
5 | 1
(6 rows)
次に、外側のクエリをその周りにラップして、上位の一致のみを剥がします。
=> select id
from (
select id,
rank() over (partition by thread_id order by created_at desc)
from posts
where receiver_id = 1
) as dt
where rank = 1;
id
----
3
6
5
(3 rows)
したがって、必要な列を追加して、すべてを Post.find_by_sql
完了です。