我有一个表,其中包含从用户a到用户b(以及更多用户)的消息,反之亦然。
我正在尝试从用户之间的任何对话中检索最后一条消息,另外我想通过消息时间降序来订购它。
我的表格如下:
+--------+----------+--------------+------------------+
| userid | touserid | messsagetime | message |
+--------+----------+---------------+------------------+
| 1 | 2 | 1504637613197 | hello |
| 1 | 2 | 1504637938942 | how are you? |
| 2 | 1 | 1504637970246 | i'm fine thanks. |
| 3 | 1 | 1504640245930 | hello |
| 1 | 3 | 1504640322756 | hello! |
+--------+----------+---------------+------------------+
预期产出:
+--------+----------+---------------+------------------+
| userid | touserid | messsagetime | message |
+--------+----------+---------------+------------------+
| 2 | 1 | 1504637970246 | i'm fine thanks. |
| 1 | 3 | 1504640322756 | hello! |
+--------+----------+---------------+------------------+`
不幸的是,我的MySQL知识是有限的,这是我得到的:
SELECT *
FROM
( SELECT *
FROM messages
WHERE userid = 1
or touserid = 1
ORDER
BY messagetime desc
) AS a
GROUP
BY userid
哪个按消息时间排序,只为from
- to
添加一条消息,但不会将来自其他用户的消息分组。
创建/插入样本数据:
CREATE TABLE IF NOT EXISTS `1` ( `id` int(11) NOT NULL
AUTO_INCREMENT, `touser` int(11) NOT NULL, `fromuser` int(11) NOT
NULL, `messagetime` bigint(20) NOT NULL, `message` text COLLATE
utf8mb4_unicode_ci NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci AUTO_INCREMENT=6 ;
INSERT INTO `1` (`id`, `touser`, `fromuser`, `messagetime`, `message`)
VALUES (1, 1, 2, 1504637613197, 'hello'), (2, 1, 2, 1504637938942,
'how are you? '), (3, 2, 1, 1504637970246, 'i''m fine thanks.'), (4,
3, 1, 1504640245930, 'hello'), (5, 1, 3, 1504640322756, 'hello!');
是否有任何MySQL魔法可以实现我在这里尝试做的事情?
答案 0 :(得分:1)
这可能是一种更快的方式,但这是我的第一次传球: http://rextester.com/FCQU57469
我们使用联合来切换touserid和fromuserId,这样我们就可以识别"对话"两个人之间。然后,我们只需获得每个配对的最大时间戳。然后,我们将其加入到基准集中,并且用户ID在一个或另一个中。这部分可能很慢。应该注意的是,如果用户A和B在不同的日期或年份进行了对话......只会返回两者之间的最新对话。
SELECT x.*
FROM (SELECT max(messageTime) mmt, A, B
FROM (SELECT touser A, fromuser B, messageTime
FROM SO46062696
UNION ALL
SELECT fromuser A, touser B, messageTime
FROM SO46062696) Z
WHERE A < B
GROUP BY A,B
) Y
INNER JOIN SO46062696 x
on Y.mmt = x.messagetime
and Y.A in (x.touser, x.fromuser)
and Y.B in (x.touser, x.fromuser)
下面带#的行可以是touser = 1的地方。
此示例:http://rextester.com/CFO21487显示A < B and Z.a=1
的位置
这是我认为你追求的; userId 1与(或来自)的所有对话及其最近的对话与唯一的合作伙伴。在这种情况下,将a视为下面的USERId,没有from或to reference。
SELECT x.*
FROM (SELECT max(messageTime) mmt, A, B
FROM (SELECT touser A, fromuser B, messageTime
FROM SO46062696
#WHERE touser = 1 #Prefered1
UNION ALL
SELECT fromuser A, touser B, messageTime
FROM SO46062696
#WHERE touser=1 #Prefered1) Z
WHERE A < B
# and Z.A = 1 #added Less Optimal
GROUP BY A,B
) Y
INNER JOIN SO46062696 x
on Y.mmt = x.messagetime
and Y.A in (x.touser, x.fromuser)
and Y.B in (x.touser, x.fromuser)
可能还有更优化的方式;但我需要了解userID 1的含义,因为userID不是数据集中的一列。