PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Aplicativo Rails 3 com PostgreSQL - Obtendo a lista de mensagens agrupadas por conversão


Se você não se importa em sujar as mãos com um pouco de SQL, você pode usar um função de janela para fazer o trabalho. Você pode obter os IDs de postagem com este 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

Se você quiser mais colunas, adicione-as a ambas as cláusulas SELECT. O #{user.id} é, obviamente, o destinatário em que você está interessado.

A parte interessante é a função da janela:
rank() over (partition by thread_id order by created_at desc)

Isso irá particionar a tabela em grupos com base em thread_id (uma espécie de GROUP BY localizado), ordene-os pelo carimbo de data/hora (mais recente primeiro) e, em seguida, rank() produz 1 para a primeira entrada em cada grupo, 2 para a segunda, etc.

Dada uma tabela que se parece com isso:
=> 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)

A consulta interna fornece isso:
=> 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)

E, em seguida, envolvemos a consulta externa em torno disso para destacar apenas as correspondências do ranking superior:
=> 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)

Então, adicione as colunas extras que você deseja e envolva tudo em um Post.find_by_sql e pronto.