我正在处理一个收件箱应用程序,并且有一个名为Messages的表,其中包含用户之间发送的所有消息。我们将其设置为对话视图。如果您答复一条消息,则第一条消息的消息ID成为所有后续答复的parentMessageID。它有几个领域,但是为此,我实际上只关心其中三个领域。带有示例数据的基本设置是:
MessageID (Guid) | Date | ParentMessageID (Guid) | recipientID
00000000 07/11/18 NULL 1
11111111 07/12/18 00000000 2
22222222 07/10/18 NULL 2
33333333 07/11/18 22222222 1
44444444 07/01/18 NULL 2
现在我有以下内容:
Select * from messages where recipientID = X AND ParentMessageID is null Order by Date DESC
这些结果将变成一个列表。此后,我遍历邮件列表,并检查是否有子邮件带有
Select top 1 * from messages where parentMessageID = X order by date desc
如果产生结果,则只需将列表中的父邮件替换为我刚刚找到的子邮件。效果很好...但是我需要能够将其转换为一个SQL查询以用于缓存,以便可以使用.Skip和.Take进行分页。
我没有运气就尝试了不同的join和group by语句,而且一旦弄清楚了,我必须确保它可以与LINQ一起使用。我们正在使用SQL Server 17。
如果使用以上数据作为参考,则期望结果集将是收件人ID 2:
MessageID (Guid) | Date | ParentMessageID (Guid) | recipientID
11111111 07/12/18 00000000 2
44444444 07/01/18 NULL 2
对于收件人1:
MessageID (Guid) | Date | ParentMessageID (Guid) | recipientID
00000000 07/11/18 2:00 NULL 1
33333333 07/11/18 1:20 22222222 1
答案 0 :(得分:0)
弄清楚如何仅使用最新的子消息后,我想到了以下解决方案:
DECLARE @X int = 2;
WITH
MsgChildNumbering (MsgID, [Date], ParentMsgID, RcptID, ChildNo) AS (
SELECT MessageID, [Date], ParentMessageID, RecipientID
, ROW_NUMBER() OVER (PARTITION BY ParentMessageID ORDER BY [Date] DESC)
FROM Messages
),
CTE_Msg (MsgID, [Date], ParentMsgID, RcptID, RootMsgID, LevelNo) AS (
SELECT MsgID, [Date], ParentMsgID, RcptID, MsgID, 1
FROM MsgChildNumbering WHERE ParentMsgID IS NULL AND RcptID = @X
UNION ALL
SELECT c.MsgID, c.[Date], c.ParentMsgID, c.RcptID, p.RootMsgID, 1+p.LevelNo
FROM MsgChildNumbering AS c -- child messages with numbering
INNER JOIN CTE_Msg AS p -- parent messages from last iteration
ON c.ParentMsgID = p.MsgID
WHERE c.ChildNo = 1
),
MsgNumbering (MsgID, [Date], ParentMsgID, RcptID, MsgNo) AS (
SELECT MsgID, [Date], ParentMsgID, RcptID
, ROW_NUMBER() OVER (PARTITION BY RootMsgID ORDER BY LevelNo DESC)
FROM CTE_Msg
)
SELECT MsgID, [Date], ParentMsgID, RcptID
FROM MsgNumbering WHERE MsgNo = 1;
@X
进行对话的所有初始消息开始,然后依次与ChildNo = 1
添加子消息(每个子消息中只有最新的父)。RootMsgID
对会话中的消息添加反向编号(与LevelNo
相同),以便能够找到每个会话的最新消息。