sql >> Database teknologi >  >> RDS >> PostgreSQL

Rails 3 app med PostgreSQL - Få listen over beskeder grupperet efter konvertering

Hvis du ikke har noget imod at blive beskidte med lidt SQL, kan du bruge en vinduefunktion at få arbejdet gjort. Du kan få post-id'erne med denne 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

Hvis du ønsker flere kolonner, skal du tilføje dem til begge SELECT-sætninger. #{user.id} er selvfølgelig den modtager, du er interesseret i.

Den interessante del er vinduesfunktionen:

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

Dette vil opdele tabellen i grupper baseret på thread_id (en slags lokaliseret GROUP BY), sorter dem efter tidsstemplet (seneste først), og derefter rank() giver 1 for den første post i hver gruppe, 2 for den anden osv.

Givet en tabel, der ser sådan ud:

=> 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 indre forespørgsel giver dig dette:

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

Og så vikler vi den ydre forespørgsel omkring det for kun at fjerne de bedste kampe:

=> 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å tilføj de ekstra kolonner, du ønsker, og pak det hele ind i en Post.find_by_sql og du er færdig.




  1. Hvad er forskellen mellem ifnull og coalesce i mysql?

  2. Gå tilbage fra SQL-forespørgsel til applikationskode?

  3. Slip flere borde i ét skud i MySQL

  4. Hvad er MariaDB ColumnStore?