如何从两个字段中选择一个? (不等于某个值?)

时间:2012-01-23 08:36:54

标签: mysql sql select unique

基本上我想要做的是在一个用户之间选择他们接收或发送消息的最新消息。这意味着我需要的唯一用户ID可以是m_to或m_from。那么如何过滤搜索以从两个字段之一中选择唯一ID,其中字段不是主要用户的ID?我在这里有道理吗?

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

所以,为了(尝试)清楚,我需要进行一个查询,以便为他们收到或发送消息的每个用户选择从主用户收到或发送的最新消息。这样,列表中没有重复的用户。但是,由于这可能是在to或from领域,我不知道如何做到这一点。有人可以帮我一把吗?

编辑:好的,显然我不清楚。 $ user_id变量是登录用户的用户ID。意思是我需要来自m_from或m_to字段的唯一消息,该字段是NOT $ user_id

编辑:

如果我们正在运行此查询...

选择   用户,   the_other_party,   MAX(日期)AS max_date FROM(   选择     CASE m_to'IxjXgC'那么m_to ELSE m_from END as the_user,     CASE m_from WHEN'IxjXgC'那么m_to ELSE m_from END as the_other_party,     日期   来自消息   在哪里m_to ='IxjXgC'      或者m_from ='IxjXgC' )m 并且假设我们在数据库中有这些类别......

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 个答案:

答案 0 :(得分:2)

如果您只希望一个用户 $ user_id ,那么您的查询几乎已完成..只需将订单反向到最新(D​​ESC)并将输出限制为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 :(得分:2)

我不会指责你是懒惰的(在这方面我不比你好,我很害怕),但我同意Andreas Rohde的意见,你应该努力将这些必要的列明确列为通常尽可能。这样做可能真的有助于你看到解决方案,否则就不那么明显了。

例如,解决你目前的问题。您需要一种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 :(得分:1)

我想你想要这个:

给定用户A,为用户A与之进行过对话的所有用户返回最新消息M.

以下语句将为您提供用户A与之交换消息的每个用户B的最长日期:

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
;

我很确定有一种不那么冗长的方式,但这应该让你开始。

答案 3 :(得分:0)

试试这个:

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

我认为这可以解决您的问题。顺便说一下,不要将*用于此类查询。建议使用您想要值的列名称。