选择按chat_id分组的行集中的max(paramValue)

时间:2018-03-09 14:33:26

标签: mysql greatest-n-per-group

我已经看到了围绕SO我的问题的几个实现,但仍然不能根据我的需要调整它。

// table:

CREATE TABLE `chat_msgs` (
`id` int(11) NOT NULL,
`chat_id` int(11) NOT NULL,
`user_to` varchar(70) NOT NULL, 
`user_from` varchar(70) NOT NULL,
`body` varchar(255) NOT NULL,
`msg_time` datetime NOT NULL,
`viewed` enum('0','1') NOT NULL DEFAULT '0' )
ENGINE=InnoDB DEFAULT CHARSET=utf8;

//虚拟聊天数据:

INSERT INTO `chat_msgs` (`id`, `chat_id`, `user_to`, `user_from`, `body`, `msg_time`, `viewed`) VALUES
(46, 1, '40', '39', '我们商谈订单细节,好码?', '2018-03-05 01:06:38', '1'),
(47, 1, '40', '39', '45', '2018-03-05 01:06:56', '1'),
(48, 1, '39', '40', 'OK?', '2018-03-05 08:12:34', '0'),
(49, 2, '39', '211', 'jk', '2018-03-05 08:27:05', '1'),
(50, 2, '211', '39', 'hj', '2018-03-05 08:27:12', '1'),
(66, 2, '39', '211', 'fe', '2018-03-06 16:44:03', '0'),
(67, 3, '39', '160', 'sdfs sdfg fg', '2018-03-08 16:44:06', '0'),
(68, 3, '39', '160', 'are yoy here my friend?', '2018-03-09 08:44:06', '0');

目标:行,其中每个唯一的chat_id我有一个最晚(按时间)行,包含:chat_id,user_to(用户,向其发送消息),user_from(发送消息的人),正文(这是消息)本身)和max(msg_time)。

基本上,它应该输出登录用户与任何其他用户的最新聊天消息。

我想出了:

SELECT * FROM  (SELECT chat_id,user_to,user_from,body,max(msg_time) FROM chat_msgs GROUP BY chat_id) t1  JOIN (SELECT chat_id,count(viewed) unviewed FROM chat_msgs WHERE viewed='0' AND user_to='39' group by chat_id) t2  on t1.chat_id=t2.chat_id
除了事实上它没有返回最新的“身体”之外,

除了最新的“身体”之外还有很多部分。

我知道我必须适合选择正确的身体的子查询,但不知何故不能达到它。感谢

2 个答案:

答案 0 :(得分:0)

以下内容可行:

    select
    chat_msgs.id,
    chat_msgs.chat_id,
    chat_msgs.user_to,
    chat_msgs.user_from,
    chat_msgs.body,
    chat_msgs.msg_time,
    chat_msgs.viewed
from chat_msgs
left join chat_msgs next_latest on (
    (
        chat_msgs.user_to = next_latest.user_to and
        chat_msgs.user_from = next_latest.user_from
    )
    or
    (
        chat_msgs.user_from = next_latest.user_to and
        chat_msgs.user_to = next_latest.user_from
    )
    )
    and
    chat_msgs.msg_time < next_latest.msg_time
where next_latest.msg_time is null
and (chat_msgs.user_to = 39 or chat_msgs.user_from = 39);

这通过选择进出用户的所有消息并将其与稍后的发送时间连接到消息来起作用,因此输出中的所有行都将具有附加到它们的下一条消息的发送时间。然后,where子句选择带有null的行作为后一条消息的时间戳 - 也就是说,后面没有消息的消息。在这种情况下,每个聊天线程应该只有一个。

答案 1 :(得分:0)

添加内部联接可以解决问题。此外,我发现自己需要从“聊天”表中获取其他数据(它有3列 - 每个用户的'request_id1'和'request_id2'和'chat_id'),因此添加了1个子查询:

SELECT t4.chat_id,t4.user_from,t4.user_to,t4.maxDate,t4.unviewed,t4.body,t4.ilocutor_uid,chats.rid1,chats.rid2 FROM 
        (SELECT t1.chat_id,t1.user_from,t1.user_to,t1.maxDate,t2.unviewed,t3.body,t3.ilocutor_uid 
        FROM 
        (SELECT chat_id,user_to,user_from,max(msg_time) maxDate FROM chat_msgs GROUP BY chat_id) t1 
        LEFT JOIN 
        (SELECT chat_id,count(viewed) unviewed FROM chat_msgs WHERE viewed='0' AND user_to=40 group by chat_id) t2 on t1.chat_id=t2.chat_id
        INNER JOIN (SELECT chat_id,body,msg_time, IF (user_to=40, user_from, user_to) ilocutor_uid FROM chat_msgs WHERE user_to=40 OR user_from=40) t3 
            on t1.maxDate=t3.msg_time) t4
    LEFT JOIN chats ON t4.chat_id = chats.chat_id ORDER BY t4.maxDate DESC

虽然我知道这很笨拙(对不起...... ^^),但它确实有效并且完全符合我的需要。

我正在寻找的是,将选择和连接的数量减少至少1.应该有一个选项可以省略最新的msg(当前,表“t4”)+相应的INNER的其他选择提取“正文” JOIN。