如何在MYSQL中选择2列的唯一组合

时间:2014-12-28 08:22:49

标签: php mysql

例如,如果我有这个消息表,并且它有这3列

╔══════════╦══════════╦══════════╦══════════╦
║ from_user║ to_user  ║ message  ║    date  ║
╠══════════╬══════════╣══════════║══════════║
║ 1        ║ 2        ║ text     ║timestamp ║
║ 1        ║ 3        ║ text     ║   ..     ║
║ 2        ║ 1        ║ text     ║   ..     ║
║ 2        ║ 3        ║ text     ║   ..     ║
║ 3        ║ 1        ║ text     ║   ..     ║
║ 1        ║ 2        ║ text     ║   ..     ║
║ 1        ║ 4        ║ text     ║   ..     ║
║ 3        ║ 1        ║ text     ║   ..     ║
╚══════════╩══════════╩══════════╩══════════╩

如果我想选择用户1拥有的所有会话(我所在的所有记录位于“_user”列中并且他位于“to_user”中,那么我希望得到用户所涉及的所有内容)这个“对话”会是:

  1. 用户1和2之间的对话
  2. 用户1和3之间的对话
  3. 用户1和4之间的对话
  4. 所以我只得到按日期排序的每个对话的1条记录(最后一条)

    ╔══════════╦══════════╦══════════╦══════════╦
    ║ from_user║ to_user  ║ message  ║    date  ║
    ╠══════════╬══════════╣══════════║══════════║
    ║ 1        ║ 2        ║ text     ║timestamp ║
    ║ 1        ║ 3        ║ text     ║   ..     ║
    ║ 2        ║ 1        ║ text     ║   ..     ║
    ║ 2        ║ 3        ║ text     ║   ..     ║
    ║ 3        ║ 1        ║ text     ║   ..     ║
    ║ 1        ║ 2        ║ text     ║   ..     ║<--- i would get this one third (conv between 1&2)
    ║ 2        ║ 3        ║ text     ║   ..     ║
    ║ 1        ║ 4        ║ text     ║   ..     ║<--- i would get this one second (conv between 1&4)
    ║ 3        ║ 1        ║ text     ║   ..     ║<--- i would get this one first (conv between 1&3)
    ╚══════════╩══════════╩══════════╩══════════╩
    

    我不确定如何解决这个问题,我应该使用GROUP BY吗?

    编辑:对话是指用户发送或接收消息,对话可以有多条消息或只有一条消息。 我标记为我想要得到的是每个对话的最后一条记录,无论是谁发送它以及谁收到它我想要用户拥有的每个对话的最后记录。

    这次尝试是我能找到我想要的最近的

    SELECT id, from_user, to_user
    FROM messages 
    WHERE (to_user = '$usr_id' OR from_user = '$usr_id') AND id IN
    (
        SELECT MAX(id)
        FROM messages
        GROUP BY from_user, to_user
    )
    

    但是我得到了每个组合的最后一条记录,例如,如果有

    id  from_user  to_user
    1       1          2
    2       1          3
    3       4          1
    4       2          1
    5       1          2
    

    输出是:

    id  from_user  to_user
    1       1          2
    2       1          3
    3       4          1
    4       2          1
    

    正如您所看到的那样,未选择ID为5的记录,因为它已重复,但ID为1和4的记录是相同的对话,其中只有一个应该被输出

1 个答案:

答案 0 :(得分:1)

出于可读性目的,我将向您展示第一个提供所需结果的查询,除非查询的用户位于to_user列上:

SELECT   from_user, to_user, max(msg_date) latest, id
FROM     messages 
WHERE    to_user = 1 
      OR from_user = 1
GROUP BY from_user, to_user
ORDER BY latest desc;

要使用group by解决此问题,您需要在用户位于to_user端时切换from_user,to_user列值。您可能还需要一个标记,&#34;切换&#34;,以指示这些情况。所以,你需要的是:

SELECT id, main_user, other_user, switched, max(msg_date) latest, msg_date, msg
FROM   (SELECT id, 1 main_user, if (from_user = 1, to_user, from_user) other_user,
               if (from_user=1, 0, 1) switched, msg_date, msg
        FROM   messages 
        WHERE  to_user = 1 
            OR from_user = 1) user_messages
GROUP BY main_user, other_user
ORDER BY msg_date desc;

在同一个查询中,您可以使用&#34;切换&#34;使用像子查询中的IF放回from_user,to_user。我现在没有把它放在容易阅读的地方。