यदि आपको अपने हाथों को थोड़ा सा SQL से गंदा करने में कोई आपत्ति नहीं है, तो आप विंडो फ़ंक्शन काम पूरा करने के लिए। आप इस SQL के साथ पोस्ट आईडी प्राप्त कर सकते हैं:
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
यदि आप अधिक कॉलम चाहते हैं तो उन्हें दोनों सेलेक्ट क्लॉज में जोड़ें। #{user.id}
बेशक, वह प्राप्तकर्ता है जिसमें आप रुचि रखते हैं।
दिलचस्प हिस्सा विंडो फ़ंक्शन है:
rank() over (partition by thread_id order by created_at desc)
यह तालिका को thread_id
. के आधार पर समूहों में विभाजित करेगा (एक स्थानीयकृत GROUP BY की तरह), उन्हें टाइमस्टैम्प (सबसे हाल के पहले), और फिर rank()
द्वारा ऑर्डर करें प्रत्येक समूह में पहली प्रविष्टि के लिए 1, दूसरे के लिए 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
और आपका काम हो गया।