Как выбрать уникальный из одного из двух полей? (что не равно определенной стоимости?) - PullRequest
2 голосов
/ 23 января 2012

По сути, я хочу выбрать самое последнее сообщение между одним пользователем, которого он либо получил, либо отправил сообщение. Это означает, что уникальный идентификатор пользователя, который мне нужен, может быть либо в m_to, либо в m_from. Итак, как я могу отфильтровать поиск, чтобы выбрать уникальный идентификатор из одного из двух полей, где поле не является идентификатором основного пользователя? Имею ли я здесь смысл?

SELECT * FROM messages
WHERE m_to = '$user_id' OR m_from = '$user_id'
ORDER BY date

Итак, чтобы (попытаться) быть понятным, мне нужно сделать запрос, который выберет самое последнее сообщение, полученное или отправленное основным пользователем, для каждого пользователя, которому он получил или отправил сообщение. Таким образом, в списке не будет дублированных пользователей. Однако, поскольку это может быть либо в поле, либо в поле, я понятия не имею, как это сделать. Кто-нибудь может помочь мне здесь?

РЕДАКТИРОВАТЬ: Хорошо, очевидно, я не был ясен. переменная $ user_id - это идентификатор пользователя, вошедшего в систему. Это означает, что мне нужны уникальные сообщения из поля m_from или m_to, которое НЕ является $ user_id

EDIT:

Если мы запустим этот запрос ...

ВЫБРАТЬ Пользователь, the_other_party, MAX (дата) AS max_date ОТ ( ВЫБРАТЬ СЛУЧАЙ m_to WHEN 'IxjXgC' THEN m_to ELSE m_from END AS the_user, ДЕЛО m_от КОГДА 'IxjXgC' THEN m_to ELSE m_from END AS the_other_party, Дата ОТ сообщений ГДЕ m_to = 'IxjXgC' ИЛИ m_from = 'IxjXgC' ) м и скажем, у нас есть эти категории в базе данных ...

m_to    m_from     date
IxjXgC  ShJiMr   2012-01-22 01:20:37
ShJiMr  IxjXgC   2012-01-22 02:22:37
LhJiM1  IxjXgC   2012-01-22 03:23:37

и я запускаю запрос выше, тогда результат становится ...

the_other_party     date
ShJiMr              2012-01-22 03:23:37

Ответы [ 4 ]

2 голосов
/ 23 января 2012

Я не буду обвинять вас в том, что вы ленивый (боюсь, я не лучше вас в этом отношении), но я согласен с Андреасом Роде в том, что вы должны постараться перечислить необходимые столбцы как как можно чаще. Это может действительно помочь вам увидеть решения, которые в противном случае были бы менее очевидными, если вообще были.

Возьмите, к примеру, вашу нынешнюю проблему. Вам нужен своего рода запрос GROUP BY, который бы игнорировал статус пользователя как отправителя / получателя. Почему, вы могли бы просто заменить отправителя получателем и наоборот, в одном случае, и оставить их неизменными в другом. Рассмотрим это тогда:

SELECT
  CASE m_to   WHEN '$user_id' THEN m_to ELSE m_from END AS the_user,
  CASE m_from WHEN '$user_id' THEN m_to ELSE m_from END AS the_other_party,
  date
FROM messages
WHERE m_to   = '$user_id'
   OR m_from = '$user_id'

Набор результатов будет содержать строки, в которых рассматриваемый пользователь всегда будет возвращаться как the_user, а другая сторона, ну, как the_other_party.

Конечно, поскольку мы убедились, что '$user' возвращается в том же столбце, можно избавиться от первого CASE:

SELECT
  '$user_id' AS the_user,
  CASE m_from WHEN '$user_id' THEN m_to ELSE m_from END AS the_other_party,
  date
FROM messages
WHERE m_to   = '$user_id'
   OR m_from = '$user_id'

То есть, если вам вообще нужен этот столбец.

В любом случае, теперь вы можете агрегировать набор результатов вышеупомянутого запроса, например, как это:

SELECT
  the_user,
  the_other_party,
  MAX(date) AS max_date
FROM (
  SELECT
    CASE m_to   WHEN '$user_id' THEN m_to ELSE m_from END AS the_user,
    CASE m_from WHEN '$user_id' THEN m_to ELSE m_from END AS the_other_party,
    date
  FROM messages
  WHERE m_to   = '$user_id'
     OR m_from = '$user_id'
) m
GROUP BY
  the_user,
  the_other_party

Вы также можете присоединиться к последнему запросу в качестве подвыбора к messages на (messages.m_to = agg.the_user OR messages.m_from = agg.the_user) AND messages.date = agg.max_date, чтобы получить остальные столбцы.

2 голосов
/ 23 января 2012

Если вы хотите, чтобы это было только для одного пользователя $ user_id ваш запрос почти завершен ... просто измените порядок следования на новейший сначала (DESC) и ограничьте вывод 1

SELECT * FROM messages 
WHERE m_to = '$user_id' OR m_from = '$user_id' 
ORDER BY date DESC 
LIMIT 1

ответ на редактирование:

SELECT * FROM messages 
WHERE not (m_to = '$user_id' OR m_from = '$user_id') 
ORDER BY date DESC 

сообщения, где пользователь является ни получателем, ни отправителем


Список людей, которые поддерживают связь с $ user_id

SELECT DISTINCT IF(m_to=$user_id, m_from, m_to)
FROM messages 
WHERE m_to = '$user_id' OR m_from = '$user_id'
ORDER BY date DESC 
1 голос
/ 23 января 2012

Я думаю, вы хотите это:

Учитывая пользователя A, вернуть последнее сообщение M для всех пользователей B, с которым пользователь A когда-либо общался.

Следующее утверждение даст вам максимальную дату для каждого пользователя B, с которым пользователь A обменивался сообщениями:

select
    m2.this_user,
    m2.other_user,
    max(m2.date) max_message_date
from    
(
    select
        m.*,
        IF(m.m_to = '$user_id', m.m_to, m.m_from) as this_user,
        IF(m.m_to = '$user_id', m.m_from, m.m_to) as other_user,
    from
        messages m
    where
        m.m_to = '$user_id'
        or m.m_from = '$user_id'
) m2
group by
    m2.this_user,
    m2.other_user
;

Используя эту информацию, вы можете получить полную информацию о сообщении, присоединившись к messages:

select
    m3.*
from
    messages m3
    inner join
    (
         select
         m2.this_user,
         m2.other_user,
         max(m2.date) max_message_date
     from    
     (
         select
             m.*,
             IF(m.m_to = '$user_id', m.m_to, m.m_from) as this_user,
             IF(m.m_to = '$user_id', m.m_from, m.m_to) as other_user,
         from
             messages m
         where
             m.m_to = '$user_id'
             or m.m_from = '$user_id'
     ) m2
     group by
         m2.this_user,
         m2.other_user
    ) d
        on  ((m3.m_to = d.this_user and m3.m_from = d.other_user) or
             (m3.m_to = d.other_user and m3.m_from = d.this_user))
        and m3.date = d.max_message_date
;

Я почти уверен, что есть менее многословный способ, но это должно помочь вам начать.

0 голосов
/ 23 января 2012

Попробуйте:

SELECT * FROM messages WHERE m_to = '$user_id' 
union
SELECT * FROM messages WHERE m_from = '$user_id' 
ORDER BY date desc Limit 1

Я думаю, что это решит вашу проблему.Кстати, не используйте * для такого рода запросов.Рекомендуется использовать имена столбцов, значения которых вы хотите получить.

...