如何按行分组,但最近的日期?

时间:2013-08-22 03:22:19

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

在我的MySQL数据库中,我有一个这样的表,用于存储来自任何人的对话消息

id               int(11)           id of the message    
from member_id   int(11)           id of the person the message was sent from
to member_id     int(11)           id of the person the message was sent to 
date sent        datetime          date of when it was sent 
active           tinyint(1)        if the message is deleted    
text             longtext          the text of the message
from_read        tinyint(1)        boolean to know if the person who sent it read it 
to_read          tinyint(1)        boolean to know if the person who it got sent to read it

例如,它可能有:

from_member_id to_member_id date sent
1              2            june 12
1              3            june 13
2              3            june 14
3              1            june 9

因此,我们在人121323之间进行了对话。

我正在尝试获取一个select语句,该语句将向我提供当前用户与用户所在的每个对话所涉及的最新消息。因此,如果1已登录,那么我希望得到2排。结果集中的第一行将是上面的第二行(7月13日),因为它是最新的,然后结果集中的第二行将是上面的第一行(6月12日),这是{{ {1}}两次对话。结果集也需要按发送日期排序,因此新的会话列在顶部。

我想要做的就像Android手机中的短信,您可以在其中看到对话列表,以及每个列表中的最新消息。

这是我的SQL查询

1

我刚刚将SELECT * FROM ( SELECT * FROM message WHERE `from member_id`=1 OR `to member_id`=1 ORDER BY IF(`from member_id`=1, `to member_id`, `from member_id`) ) as t GROUP BY IF(`from member_id`=1, `to member_id`, `from member_id`) 硬编码为现在的用户。我正在做的是,用我可以使用if语句检查的另一个人的id对它们进行排序,然后对该结果进行分组,以便我尝试从每个对话中获取最近的一个。

问题是,在分组时,每个组可以有超过1行,而且它似乎只是选择一些随机行。如何让它选择具有最新日期发送值的行?

2 个答案:

答案 0 :(得分:2)

你在找这样的东西吗?

SELECT m.*
  FROM message m JOIN
(
  SELECT from_member_id, to_member_id, MAX(date_sent) date_sent
    FROM message
   WHERE from_member_id = 1
   GROUP BY from_member_id, to_member_id
) q
    ON m.from_member_id = q.from_member_id
   AND m.to_member_id = q.to_member_id
   AND m.date_sent = q.date_sent
 ORDER BY date_sent DESC

示例输出:

| FROM_MEMBER_ID | TO_MEMBER_ID |  DATE_SENT |
----------------------------------------------
|              1 |            3 | 2013-06-13 |
|              1 |            2 | 2013-06-12 |

这是 SQLFiddle 演示

<强>更新

SELECT m.*
  FROM message m JOIN
(
  SELECT LEAST(from_member_id, to_member_id) least_id, 
         GREATEST(from_member_id, to_member_id) greatest_id, 
         MAX(date_sent) date_sent
    FROM message
   WHERE from_member_id = 1 
      OR to_member_id   = 1
   GROUP BY    LEAST(from_member_id, to_member_id),
            GREATEST(from_member_id, to_member_id)
) q
    ON LEAST(m.from_member_id, m.to_member_id) = q.least_id
   AND GREATEST(m.from_member_id, m.to_member_id) = q.greatest_id
   AND m.date_sent = q.date_sent
 ORDER BY date_sent DESC

示例输出:

| FROM_MEMBER_ID | TO_MEMBER_ID |  DATE_SENT |
----------------------------------------------
|              3 |            1 | 2013-06-14 |
|              1 |            2 | 2013-06-12 |

这是 SQLFiddle 演示

答案 1 :(得分:0)

SELECT
  *
FROM message m INNER JOIN
  (
    SELECT
      from_menber_id,
      MAX(date_sent) AS sentdate
    FROM message s
    GROUP BY from_menber_id
  ) AS a
    ON m.date_sent = a.sentdate AND a.from_menber_id = m.from_menber_id