PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Rails 3-App mit PostgreSQL - Abrufen der nach Konversion gruppierten Nachrichtenliste

Wenn es Ihnen nichts ausmacht, sich mit ein bisschen SQL die Hände schmutzig zu machen, können Sie ein Fensterfunktion um die Arbeit zu erledigen. Sie können die Beitrags-IDs mit diesem SQL abrufen:

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

Wenn Sie mehr Spalten wünschen, fügen Sie diese beiden SELECT-Klauseln hinzu. Der #{user.id} ist natürlich der Empfänger, an dem Sie interessiert sind.

Der interessante Teil ist die Fensterfunktion:

rank() over (partition by thread_id order by created_at desc)

Dadurch wird die Tabelle basierend auf thread_id in Gruppen aufgeteilt (eine Art lokalisiertes GROUP BY), ordnen Sie sie nach Zeitstempel (neueste zuerst) und dann nach rank() ergibt 1 für den ersten Eintrag in jeder Gruppe, 2 für den zweiten usw.

Gegeben sei eine Tabelle, die so aussieht:

=> 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)

Die innere Abfrage gibt Ihnen Folgendes:

=> 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)

Und dann wickeln wir die äußere Abfrage darum herum, um nur die Top-Ranking-Matches abzuschälen:

=> 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)

Fügen Sie also die gewünschten zusätzlichen Spalten hinzu und verpacken Sie alles in einem Post.find_by_sql und fertig.