获取每组的最后一行

Posted

技术标签:

【中文标题】获取每组的最后一行【英文标题】:Get last row PER Group 【发布时间】:2011-03-27 01:03:09 【问题描述】:

如何为以下任务制定查询:

假设您以 user:1 身份登录 我想在我进行过的每个对话中获得一排。 对于我想获得的每一行, 对话中第一行的“主题” 第一行的“日期时间” “消息”此对话的最后一条消息,无论是谁写的

创建表消息(
    ID INT NOT NULL AUTO_INCREMENT 主键,
    FromID INT NOT NULL,
    ToID INT NOT NULL,
    对话ID INT NOT NULL,
    主题 varchar(255),
    消息 varchar(255),
    日期时间日期时间
    ) 引擎=InnoDB;


CREATE TABLE 对话(
    ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY
    ) 引擎=InnoDB;



插入对话(ID)值(1),(2),(3);
INSERT INTO messages (FromID, ToID, ConversationID, Subject, Message, DateTime) VALUES (1,2, 1, "Hi", "This is a test message", "2010-08-08 16:23:48");
插入消息(FromID、ToID、ConversationID、主题、消息、日期时间)值(1,2、1、“”、“嘿,你还没有回答”、“2010-08-08 16:23:52”);
插入消息(FromID、ToID、ConversationID、主题、消息、日期时间)值(2,1、1、“”、“嗨,这是我的答案”、“2010-08-08 16:23:59”);


INSERT INTO messages (FromID, ToID, ConversationID, Subject, Message, DateTime) VALUES (2,1, 2, "2.Hi", "2.This is a test message", "2010-08-08 16:25: 48");
插入消息(FromID、ToID、ConversationID、主题、消息、日期时间)值(1,2、2、“”、“2.Hi back”、“2010-08-08 16:25:52”);
插入消息(FromID、ToID、ConversationID、主题、消息、日期时间)值(2,1、2、“”、“2.Hi 这是我的答案”、“2010-08-08 16:25:59”) ;


INSERT INTO messages (FromID, ToID, ConversationID, Subject, Message, DateTime) VALUES (2,1, 3, "3.Hi", "3.This is a test message", "2010-08-08 16:27: 48");
插入消息(FromID、ToID、ConversationID、主题、消息、日期时间)值(1,2、3、“”、“2.Hi back”、“2010-08-08 16:27:52”);
插入消息(FromID、ToID、ConversationID、主题、消息、日期时间)值(1,2、3、“”、“2.你在吗?”、“2010-08-08 16:27:59”) ;

【问题讨论】:

是否只能在 2 个人之间进行对话?即,会话中所有消息的用户 ID 是 FromID 还是 ToID 是的,只有两个人的对话 【参考方案1】:

看看@ROW_NUMBER() in mysql - 你肯定能把它应用到你的问题上。

【讨论】:

【参考方案2】:
SELECT M.ConversationID, 
MAX(CASE WHEN M.DateTime = X.FirstRow THEN M.Subject END) AS Subject,
CAST(COALESCE(MAX(CASE WHEN M.DateTime = X.LastRowSentByOtherUser 
                       THEN M.DateTime END),X.LastRow) AS DateTime)AS LastTime,
MAX(CASE WHEN M.DateTime = X.LastRow THEN M.Message END) AS Message,
MAX(CASE WHEN FromID = 1 THEN ToID ELSE FromID END) AS OtherParticipantId
FROM messages M
JOIN (
    SELECT ConversationID, MIN(DateTime) AS FirstRow, MAX(DateTime) AS LastRow,
    MAX(CASE WHEN FromID<>1 THEN DateTime END) AS LastRowSentByOtherUser
    FROM messages
    WHERE FromID=1 OR ToID=1
    GROUP BY ConversationID
) X ON X.ConversationID = M.ConversationID
AND (M.DateTime IN (X.FirstRow, X.LastRow, X.LastRowSentByOtherUser))
GROUP BY M.ConversationID
HAVING MAX(CASE WHEN M.DateTime = X.LastRowSentByOtherUser 
                   THEN M.DateTime END) IS NOT NULL

【讨论】:

嗨马丁,这很好!只是几件事,我收到的消息不是对话中的最新消息,而我真正要查找的 DateTime 是另一个用户在此对话中发送的最后一条消息的时间。 我认为问题可能是您的测试表中的NOW() 意味着所有日期时间都相同?如果是这样,可以使用 id 代替。 没错就是这样!这几乎是完美的,我用新数据编辑了帖子。最后一件事,我怎样才能获得与我对话的用户的 ID 也为每一行(对话) 我认为我的编辑应该适用于明确的规范,但显然可以根据一些数据对其进行测试! 哇 :) 不会想到这一点,非常感谢,很抱歉添加我现在才意识到的一些内容,但我是否也可以获得与每个返回行进行对话的用户的 ID? 【参考方案3】:

你应该试试这样的:

SELECT 
   m1.Subject,
   m1.DateTime,
   m2.Message
FROM conversations c 
INNER JOIN 
   (SELECT MIN(ID) AS minID, 
           MAX(ID) AS maxID, 
           ConversationID
   FROM messages
   WHERE FromID = @userID OR ToID = @userID
   GROUP BY ConversationID) AS cGrouped
ON c.ConversationID = cGrouped.ConversationID
INNER JOIN messages m1 ON m1.ID = cGrouped.minID
INNER JOIN messages m2 ON m2.ID = cGrouped.maxID

【讨论】:

以上是关于获取每组的最后一行的主要内容,如果未能解决你的问题,请参考以下文章

只用 pandas 获取每组的第一行和最后一行

如何在 SQL 中获取每组的最后一条记录

窗口函数从每个组中获取第一行和最后一行

获取每组的前 n 个结果 [重复]

获取第n个连续组的第一行/最后一行

获取每组的最大值