列出按所有用户的会话排序的消息

时间:2015-11-11 14:26:02

标签: mysql sql greatest-n-per-group

我的用例是一个管理视图,用于查看数据库中的所有消息。

我想要一个按对话和开始日期排序的消息列表,其目的是能够在其上下文中查看每条消息。

对话是两个用户之间的互动列表。

我没有conversation表,只有message表。

从这个数据样本:

id   sender      recipient
--------------------------
1    marc        rémi
2    gépéto      sylvain
3    rémi        marc
4    julie       georgette
5    rémi        marc
6    denis       julie
7    julie       rémi
8    sylvain     gépéto
9    denis       marc
10   denis       julie

我想获得:

id   sender      recipient
--------------------------
1    marc        rémi
3    rémi        marc
5    rémi        marc
2    gépéto      sylvain
8    sylvain     gépéto
4    julie       georgette
6    denis       julie
10   denis       julie
7    julie       rémi
9    denis       marc

目前,我更愿意将每次对话的第一条消息作为迈向想要结果的第一步:

SELECT message.id, message.sender , message.recipient
FROM message
GROUP BY message.sender, message.recipient
HAVING message.id = min(message.id)
ORDER BY message.id DESC;

但是我无法做到这一点,我得到两个对话而不是一个用于所有双向对话:

id   sender      recipient
--------------------------
8    sylvain     gépéto
2    gépéto      sylvain

所以,我被困在这里......我会很感激一些提示!

几乎忘了:SQL Fiddle with the sample and the last query

3 个答案:

答案 0 :(得分:4)

您可以使用以下查询获取每个会话的第一条消息的id

SELECT MIN(id),
       IF(sender > recipient, sender, recipient) AS participantA, 
       IF(sender > recipient, recipient, sender) AS participantB
FROM message 
GROUP BY participantA, participantB

现在在派生表中使用上述查询来获得所需的结果:

SELECT id, sender, recipient
FROM (
  SELECT id, sender, recipient,
         IF(sender > recipient, sender, recipient) AS participantA, 
         IF(sender > recipient, recipient, sender) AS participantB
  FROM message) AS t1
INNER JOIN (  
  SELECT MIN(id) AS minId,
         IF(sender > recipient, sender, recipient) AS participantA, 
         IF(sender > recipient, recipient, sender) AS participantB
  FROM message 
  GROUP BY participantA, participantB
) AS t2 ON t1.participantA = t2.participantA AND t1.participantB = t2.participantB
ORDER BY t2.minId

Demo here

答案 1 :(得分:2)

<强> SqlFiddle Demo

SELECT m.*, CASE 
                WHEN sender <= recipient THEN concat(sender,'-',recipient)
                ELSE concat(recipient,'-', sender)
            END as conversation
FROM message m
ORDER BY conversation, id

<强>输出

| id |  sender | recipient |    conversation |
|----|---------|-----------|-----------------|
|  6 |   denis |     julie |     denis-julie |
| 10 |   denis |     julie |     denis-julie |
|  9 |   denis |      marc |      denis-marc |
|  4 |   julie | georgette | georgette-julie |
|  2 |  gépéto |   sylvain |  gépéto-sylvain |
|  8 | sylvain |    gépéto |  gépéto-sylvain |
|  7 |   julie |      rémi |      julie-rémi |
|  1 |    marc |      rémi |       marc-rémi |
|  3 |    rémi |      marc |       marc-rémi |
|  5 |    rémi |      marc |       marc-rémi |

这是第一个方法,如果您首先需要marc-rémi,则需要包含另一个选择以获得每个会话的MIN()

精确解决方案 SqlFiddleDemo

SELECT conversation_id, T.id, T.sender, T.recipient, T.conversation
FROM (
    SELECT CASE 
               WHEN sender <= recipient THEN concat(sender,'-',recipient)
               ELSE concat(recipient,'-', sender)
           END as conversation,
           MIN(id) as conversation_id
    FROM message m
    GROUP BY conversation    
    ) as convesation_start
JOIN (
    SELECT m.*, CASE 
                    WHEN sender <= recipient THEN concat(sender,'-',recipient)
                    ELSE concat(recipient,'-', sender)
                END as conversation
    FROM message m
    ) as T
  ON 
  convesation_start.conversation = T.conversation
ORDER BY conversation_id, T.id

<强>输出

| conversation_id | id |  sender | recipient |    conversation |
|-----------------|----|---------|-----------|-----------------|
|               1 |  1 |    marc |      rémi |       marc-rémi |
|               1 |  3 |    rémi |      marc |       marc-rémi |
|               1 |  5 |    rémi |      marc |       marc-rémi |
|               2 |  2 |  gépéto |   sylvain |  gépéto-sylvain |
|               2 |  8 | sylvain |    gépéto |  gépéto-sylvain |
|               4 |  4 |   julie | georgette | georgette-julie |
|               6 |  6 |   denis |     julie |     denis-julie |
|               6 | 10 |   denis |     julie |     denis-julie |
|               7 |  7 |   julie |      rémi |      julie-rémi |
|               9 |  9 |   denis |      marc |      denis-marc |

答案 2 :(得分:1)

我想出了这个:

SELECT id, sender, recipient
FROM (SELECT message.id, message.sender , message.recipient
            ,concat(greatest(message.sender,message.recipient)
                   ,least(message.sender,message.recipient)
                   ) as conv
       FROM message) as tab1
INNER JOIN 
    (SELECT min(id) as min
           ,concat(greatest(message.sender,message.recipient)
                  ,least(message.sender,message.recipient)
                  ) as conv
      FROM message 
    GROUP BY conv) as tab2
ON tab1.conv = tab2.conv
ORDER BY tab2.min
  • 其中conv是每对夫妇的标识符

这是演示:http://sqlfiddle.com/#!9/fc66b/41