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 и использует временную таблицу. Вывод - если важно отфильтровать дубли только в какой-то конкретной колонке то:
- можно указать distinct у конкретного поля (distinct from_id), не для этого случаях, вспомнить подходящий с ходу не удалось
- можно указать 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