PostgreSQL加入到表之间的最新记录

时间:2011-11-26 04:55:05

标签: postgresql join left-join

我有两个与此问题相关的表:conversations有许多messages。基本结构(仅包含相关列)如下:

conversations (
  int id (PK)
)

create table conversation_participants (
  int id (PK),
  int conversation_id (FK conversations),
  int user_id (FK users),
  unique key on [conversation_id, profile_id]
)

create table messages (
  int id (PK),
  int conversation_id (FK conversations),
  int sender_id (FK users),
  int recipient_id (FK users),
  text body
)

对于每个会话条目,我希望收到user_id

  • 用户参与的所有对话(即:conversations.*
  • 加入了最新的匹配消息(即:order by messages.id desc limit 1
  • 按最近的消息ID排序的对话(即:messages.id desc订购)

不幸的是,所有查询帮助我似乎都可以找到类似MySQL的东西,而这在PostgreSQL中不起作用。我找到的最接近的是this answer on StackOverflow,它提供了select distinct on (...)语法的示例。但是,除非我做错了,否则我似乎无法以正确的方式对结果进行排序,因为我需要使用该方法进行分组约束。

2 个答案:

答案 0 :(得分:5)

所有信息都在“消息”表中,您不需要其他表:

SELECT 
    id, 
    body,
    c.* -- content from conversations 
FROM messages 
    JOIN
        (SELECT MAX(id) AS id, conversation_id 
        FROM messages 
        WHERE 1 IN(sender_id, recipient_id) -- the number is the userid, should be dynamic
        GROUP BY conversation_id) sub
        USING(id, conversation_id)
    JOIN conversations c ON c.id = messages.conversation_id
ORDER BY
    id DESC;

编辑:只需加入“对话”即可获得此表所需的数据。

答案 1 :(得分:1)

试试这个:

select
    *
from
    conversation_participants cp

    join conversations c on
    c.id = cp.conversation_id

    -- assuming you only want the conversations where a
    -- message has been left. otherwise use left join
    join messages m on
    m.conversation_id = cp.conversation_id
    and m.id = (
            select
                    id
            from
                    messages _m
            where
                    _m.conversation_id = m.conversation_id
                    and sender_id = 1
            order by
                    id desc
            limit 1
    )
where
        cp.user_id = 1
order by
        m.id desc;