sql >> Databasteknik >  >> RDS >> PostgreSQL

Rails 3-app med PostgreSQL - Få listan över meddelanden grupperade efter konversation

Om du inte har något emot att smutsa ner händerna med lite SQL kan du använda en fönsterfunktion för att få jobbet gjort. Du kan få post-ID:n med denna 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

Om du vill ha fler kolumner lägg till dem i båda SELECT-satserna. #{user.id} är naturligtvis den mottagare du är intresserad av.

Det intressanta är fönsterfunktionen:

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

Detta kommer att dela upp tabellen i grupper baserade på thread_id (typ av en lokaliserad GROUP BY), ordna dem efter tidsstämpeln (senaste först) och sedan rank() ger 1 för den första posten i varje grupp, 2 för den andra osv.

Med tanke på en tabell som ser ut så här:

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

Den inre frågan ger dig detta:

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

Och sedan lindar vi den yttre frågan runt det för att bara ta bort topprankade matcher:

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

Så lägg till de extra kolumner du vill ha och slå ihop det hela i en Post.find_by_sql och du är klar.




  1. PHP Mysql Json och arabiska språket

  2. Refaktorera främmande nyckel till fält

  3. mysql COUNT() antal rader för långsamt

  4. CriteriaQuery månad och år filter