最后一条消息发送逻辑问题
Last message sent logic issue
我正在尝试识别 SQL 中一组对话的对话中发送的最后一条消息。我可以找回正确的用户和 ID 没问题,但最后一条消息和它发送的时间对于两个对话返回相同,而我需要在该特定对话中发送的最后一条消息。
这是我正在使用的SQL:
SELECT ConversationId,
(SELECT Username FROM dbo.[User] WHERE (UserId = dbo.Conversation.FromUser)) AS FromUser,
(SELECT Username
FROM dbo.[User] User_1
WHERE (UserId = dbo.Conversation.ToUser)) AS ToUser,
(SELECT TOP (1)
MessageBody
FROM dbo.ConversationMessage
WHERE (ConversationId = ConversationId)
ORDER BY MessageDateTime DESC) AS LastMessageBody,
(SELECT TOP (1)
CONVERT(varchar(5), MessageDateTime, 114) AS Expr1
FROM dbo.ConversationMessage ConversationMessage_1
WHERE (ConversationId = ConversationId)
ORDER BY MessageDateTime DESC) AS LastMessageTime
FROM dbo.Conversation;
这是我要返回的结果集,只是为了清楚起见:
LastMessageBody 和 LastMessageTime 应该都是唯一的,并且由于 ConversationId 都是唯一的,所以我不明白为什么每次都应该返回相同的消息。我的理解是,单个行的 ConversationId 将在 where 子句中使用,就像其他列中的 UserId 一样?
只要您在查询中有多个 table,总是 使用 table 别名和限定的列名。这是你的问题。
这里是一个如何修复它的例子:
SELECT . . .
(SELECT TOP (1) cm.MessageBody
FROM dbo.ConversationMessage cm
WHERE cm.ConversationId = c.ConversationId
ORDER BY cm.MessageDateTime DESC
) AS LastMessageBody,
. . .
FROM dbo.Conversation c;
当所有 列名称都正确限定时,您的查询应该会按预期工作。
老实说,这是在黑暗中进行的一次大规模尝试,但是,可能 就是您想要的。这里没有示例数据或预期结果,所以如果这不是您需要的,请同时提供。
我也摆脱了那些糟糕的子查询并用 JOIN
s:
替换了它们
SELECT TOP 1 WITH TIES
C.ConversationId,
Uf.Username AS FromUser,
Ut.Username AS ToUser,
CM.MessageBody AS LastMessageBody,
CONVERT(time(0),CM.MessageDateTime) AS LastMessageTime
FROM dbo.[Conversation] C
JOIN dbo.[User] Uf ON C.FromUser = Uf.UserId
JOIN dbo.[User] Ut ON C.ToUser = Ut.UserId
JOIN dbo.ConversationMessage CM ON C.ConversationId = CM.ConversationId
ORDER BY ROW_NUMBER() OVER (PARTITION BY C.ConversationId ORDER BY CM.MessageDateTime DESC);
我正在尝试识别 SQL 中一组对话的对话中发送的最后一条消息。我可以找回正确的用户和 ID 没问题,但最后一条消息和它发送的时间对于两个对话返回相同,而我需要在该特定对话中发送的最后一条消息。
这是我正在使用的SQL:
SELECT ConversationId,
(SELECT Username FROM dbo.[User] WHERE (UserId = dbo.Conversation.FromUser)) AS FromUser,
(SELECT Username
FROM dbo.[User] User_1
WHERE (UserId = dbo.Conversation.ToUser)) AS ToUser,
(SELECT TOP (1)
MessageBody
FROM dbo.ConversationMessage
WHERE (ConversationId = ConversationId)
ORDER BY MessageDateTime DESC) AS LastMessageBody,
(SELECT TOP (1)
CONVERT(varchar(5), MessageDateTime, 114) AS Expr1
FROM dbo.ConversationMessage ConversationMessage_1
WHERE (ConversationId = ConversationId)
ORDER BY MessageDateTime DESC) AS LastMessageTime
FROM dbo.Conversation;
这是我要返回的结果集,只是为了清楚起见:
LastMessageBody 和 LastMessageTime 应该都是唯一的,并且由于 ConversationId 都是唯一的,所以我不明白为什么每次都应该返回相同的消息。我的理解是,单个行的 ConversationId 将在 where 子句中使用,就像其他列中的 UserId 一样?
只要您在查询中有多个 table,总是 使用 table 别名和限定的列名。这是你的问题。
这里是一个如何修复它的例子:
SELECT . . .
(SELECT TOP (1) cm.MessageBody
FROM dbo.ConversationMessage cm
WHERE cm.ConversationId = c.ConversationId
ORDER BY cm.MessageDateTime DESC
) AS LastMessageBody,
. . .
FROM dbo.Conversation c;
当所有 列名称都正确限定时,您的查询应该会按预期工作。
老实说,这是在黑暗中进行的一次大规模尝试,但是,可能 就是您想要的。这里没有示例数据或预期结果,所以如果这不是您需要的,请同时提供。
我也摆脱了那些糟糕的子查询并用 JOIN
s:
SELECT TOP 1 WITH TIES
C.ConversationId,
Uf.Username AS FromUser,
Ut.Username AS ToUser,
CM.MessageBody AS LastMessageBody,
CONVERT(time(0),CM.MessageDateTime) AS LastMessageTime
FROM dbo.[Conversation] C
JOIN dbo.[User] Uf ON C.FromUser = Uf.UserId
JOIN dbo.[User] Ut ON C.ToUser = Ut.UserId
JOIN dbo.ConversationMessage CM ON C.ConversationId = CM.ConversationId
ORDER BY ROW_NUMBER() OVER (PARTITION BY C.ConversationId ORDER BY CM.MessageDateTime DESC);