2016-09-06 5 views
0

У меня есть таблица apps. Каждое приложение имеет множество conversations и users. В разговоре много messages, и каждое сообщение может принадлежать visitor или user, а visitor может иметь много разговоров.Duplicates results in query

Для каждого из моих разговоров я хочу прикрепить имя и аватар пользователя, который недавно написал в разговоре.

Если ни один пользователь не ответил, вместо этого я хотел бы захватить 3 последних созданных пользователя avatars вместе с именем приложения и использовать их вместо этого.

Это то, что у меня до сих пор, но он возвращает несколько результатов за тот же разговор идентификатор, и я не нашел решение, чтобы получить пользователь приложения аватары

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 

Любой помощи в значительной степени оценивается

+0

Я не уверен, что это решает. Недавно ответил, что вы хотите получить последнюю вставленную строку для этой конкретной беседы. Вы пытались использовать MIN/MAX() для этого разговора? Было бы лучше, если бы вы отображали структуру таблицы и образец. –

+0

Предоставьте образцы данных в пределах желаемого результата, и я смогу помочь :) – kbball

ответ

1

Для каждого из моих разговоров я хочу прикрепить имя и аватар пользователя, который недавно написал в разговоре.

Чтобы сделать это, вы можете использовать латеральной подзапрос, но вы также должны добавить 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 
+0

Это прекрасно, большое вам спасибо – Tarlen