@exxagw

Как убрать дубликаты в mysql запросе?

Есть таблица
id |  from_id | to_id 
--------------------
1  | 5  | 6
2  | 5  | 7
3  | 5  | 8
4  | 6  | 5
5  | 8  | 6


Нужно из нее получить все from_id & to_id связанные с 5, т.е.

пользователь с id 5 написал сообщение пользователю 7, пользователю 8 и получил, например, сообщение от 7 и 6
Нужно узнать всех пользователей, проще говоря вывести с кем он общался
  • Вопрос задан
  • 12652 просмотра
Решения вопроса 1
@mantyr
Пишу много Golang кода с удовольствием:)
SELECT distinct to_id FROM messages WHERE from_id = 5
SELECT distinct from_id FROM messages WHERE to_id = 5

Почитайте более подробно тут: www.mysql.ru/docs/man/DISTINCT_optimisation.html

Одним запросом можно сделать через UNION (объединение нескольких запросов)
SELECT to_id as user_id FROM messages WHERE from_id = 5
UNION
SELECT from_id as user_id FROM messages WHERE to_id = 5

Подробнее про UNION и DISTINCT с его участием тут: www.mysql.ru/docs/man/UNION.html

Если не используется ключевое слово ALL для UNION, все возвращенные строки будут уникальными, так как по умолчанию подразумевается DISTINCT для всего результирующего набора данных. Если указать ключевое слово ALL, то результат будет содержать все найденные строки из всех примененных команд SELECT.

И ещё один способ с обычным DISTINCT одним запросом:
SELECT
    DISTINCT IF(to_id = 5, from_id, to_id) as user_id
FROM messages
WHERE from_id = 5
    OR to_id = 5


Для тех кому лень читать ссылки: DISTINCT во многих случаях разворачивается в GROUP BY и использует временную таблицу. Вывод - если важно отфильтровать дубли только в какой-то конкретной колонке то:
  1. можно указать distinct у конкретного поля (distinct from_id), не для этого случаях, вспомнить подходящий с ходу не удалось
  2. можно указать GROUP BY и перечислить нужные поля не указывая DISTINCT


Подсчёт дополнительной колонки unread и вывод даты последнего сообщения:
SELECT
    IF(to_id = 5, from_id, to_id) as user_id,
    SUM(unread) as count_unread,
    MAX(create_date) as last_create_date
FROM messages
WHERE from_id = 5
    OR to_id = 5
GROUP BY user_id


Добавляем LEFT JOIN (хотя их использовать и не стоит)
SELECT
    IF(m.to_id = 5, m.from_id, m.to_id) as user_id,
    SUM(m.unread) as count_unread,
    MAX(m.create_date) as last_create_date,
    u.name,
    u.login
FROM messages as m
    LEFT JOIN users as u ON (u.user_id = m.from_id OR u.user_id = m.to_id)
WHERE m.from_id = 5
    OR m.to_id = 5
GROUP BY user_id
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
petermzg
@petermzg
Самый лучший программист
select from_id from table where to_id = 5
union
select to_id from table where from_id = 5
Ответ написан
Ваш ответ на вопрос

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

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