@freeeeez

Как сгруппировать диалоги по двум полям в MySQL через GroupBY?

Есть таблица dialogs с диалогами по товарам пользователя, поля таблицы id, tovar_id, sender_id, recipient_id, message как вывести список диалогов чтобы они не повторялись? Каждый диалог содержит ID товара, ID того кто написал и ID кому он написал. Соответственно если идет переписка между пользователями id=1 и id=2, то в таблицы будут следующие строки:
- id=1, tovar_id=1, sender_id=1, recipient_id=2, message='привет'
- id=2, tovar_id=1, sender_id=2, recipient_id=1, message='hello'
Если group by tovar_id, sender_id, recipient_id то выводится две строки, хотя это один диалог. По tovar_id=1может вестись переписка с другими пользователями,
- id=3, tovar_id=1, sender_id=101, recipient_id=1, message='new message'
поэтому не подходит просто группировка по tovar_id
  • Вопрос задан
  • 89 просмотров
Решения вопроса 1
@alexalexes
Пробуйте этот запрос с вычисленным псевдопараметром dialog_hold.
Суть в том, что этот параметр одинаковый для переписки пользователя 1 и пользователя 2 в ту и другую сторону.
Должно получаться число 1000002 при sender_id=1, recipient_id=2 и при sender_id=2, recipient_id=1.
По этому параметру можно отсортировать переписку так, чтобы беседы пользователей шли по порядку.
Значение 1000000 должно быть заведомо большое, чем возможно число пользователей в вашей системе в любой исторический период. Однако, max(user_id) * 1000000 + max(user_id) никогда не должно превышать макс. целочисленное значение, с которым может работать СУБД (верхний предел id пользователей, когда этот финт ушами способен работать).
select a.*
from (select d.id, d.tovar_id, d.sender_id, d.recipient_id, d.message,
             case
               when d.sender_id < d.recipient_id
               then d.sender_id * 1000000 + d.recipient_id
               else d.recipient_id * 1000000 + d.sender_id
             end dialog_hold
        from dialogs d
       where d.tovar_id = :tovar_id
         and (d.sender_id = :user_id or d.recipient_id = :user_id)
      ) a
order by  a.tovar_id, a.dialog_hold, a.id
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
LaRN
@LaRN
Senior Developer
Можно вот так попробовать:

select dd.tovar_id, dd.sender_id
  from dialogs dd
 where not exists(select 1
                    from dialogs ds
                   where ds.tovar_id     = dd.tovar_id
                     and ds.recipient_id = dd.dd.sender_id
                     and ds.id           < dd.id)
 group by dd.tovar_id, dd.sender_id


Тут будут все диалоги по всем товарам.
Если нужно фильтровать по пользователю или товару, можно это сделать задав секцию where
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы