重复导致查询

时间:2016-09-06 17:16:38

标签: sql postgresql

我有一个apps表。每个应用都有很多conversationsusers。对话有很多messages,每条消息都可以属于visitoruser,而visitor可以有很多对话。

对于我的每个对话,我想附上最近在对话中写过的用户的姓名和头像。

如果没有用户回复,那么我想抓住最近创建的3个用户avatars以及该应用的名称,并改为使用这些用户。

这是我迄今为止所获得的内容,但它会针对相同的会话ID返回多个结果,而且我还没有找到获取应用用户头像的解决方案

select
        c.id,
        c.last_message,
        c.last_activity,
        coalesce(last.display_name, a.name || ' Team') as name,
        array_agg(last.avatar)
      from messages m
      left join conversations c on c.id = m.conversation_id
      left join apps a on a.id = c.app_id
      left join lateral (
          select u.id, u.display_name, u.avatar
          from users u
          where u.id = m.user_id
      ) as last on true
      where c.visitor_id = 'c6p77hu9v000a4zcth4lnefn9'
      group by c.id, last.display_name, last.avatar, a.name
      order by c.inserted_at desc

非常感谢任何帮助

1 个答案:

答案 0 :(得分:1)

  

对于我的每个对话,我想附上最近在对话中写过的用户的姓名和头像。

为此,您可以使用LATERAL子查询,但您还需要以最后一条消息的方式添加ORDER BY,然后使用LIMIT 1仅获取最后一行。因此,如果我假设您在message_datetime表中有一列message,它存储了邮件发送的日期和时间,您可以使用:

select
      c.id,
      c.last_message,
      c.last_activity,
      coalesce(last.display_name, a.name || ' Team') as name,
      last.avatar
from
    conversations c
    left join apps a on a.id = c.app_id
    left join lateral (
        select
            u.id, u.display_name, u.avatar
        from
            users u
            inner join messages m on u.id = m.user_id
        where
            c.id = m.conversation_id
        order by
            m.message_datetime desc
        limit 1
    ) as last on true
where
    c.visitor_id = 'c6p77hu9v000a4zcth4lnefn9'
order by
    c.inserted_at desc
  

如果没有用户回复,那么我想抓住3个最近创建的用户的头像以及应用程序的名称,然后使用这些。

这更简单,因为此查询与之前的查询不相关。假设您的users列有created_datetime列,其中包含创建用户的日期和时间,您可以使用简单查询:

select
    u.id, u.display_name, u.avatar
from
    users u
order by
    u.created_datetime desc
limit 3

因此您可以在上一个查询中将其用作子查询,使用COALESCE来控制要使用的信息:

select
      c.id,
      c.last_message,
      c.last_activity,
      coalesce(last.display_name, a.name || ' Team') as name,
      coalesce(array[last.avatar], last_all.avatar) as avatar
from
    conversations c
    left join apps a on a.id = c.app_id
    left join lateral (
        select
            u.id, u.display_name, u.avatar
        from
            users u
            inner join messages m on u.id = m.user_id
        where
            c.id = m.conversation_id
        order by
            m.message_datetime desc
        limit 1
    ) as last on true
    left join (
        select
            array_agg(u.avatar) as avatar
        from
            users u
        order by
            u.created_datetime desc
        limit 3
    ) last_all on true
where
    c.visitor_id = 'c6p77hu9v000a4zcth4lnefn9'
order by
    c.inserted_at desc