【问题标题】:Last message sent logic issue最后一条消息发送逻辑问题
【发布时间】:2018-08-17 15:46:11
【问题描述】:

我正在尝试为 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 一样?

【问题讨论】:

  • 您的查询比您的描述复杂得多。我很难弄清楚真正的问题是什么。
  • 这是获取数据的糟糕方式。尝试使用连接而不是子查询
  • 解释为什么你得到重复值,条件WHERE (ConversationId = ConversationId)总是true,你没有将子查询中的值与外部Conversation表关联
  • 一开始我确实尝试过加入,但因为我不止一次加入表,我无法让它工作
  • @WebDevelopWolf 以格式正确的文本提供一些示例数据和您的预期结果。它将帮助人们更好地了解您的需求。

标签: sql sql-server where-clause


【解决方案1】:

老实说,这是在黑暗中的一次巨大的尝试,但是,可能就是你所追求的。此处没有示例数据或预期结果,因此如果这不是您需要的,请同时提供。

我也摆脱了那些糟糕的子查询,并用JOINs 替换它们:

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);

【讨论】:

  • 虽然我确实投了赞成票,但我认为操作员不想要TOP 1
  • @Lamak 嗯,正如我所说,这是黑暗中的巨大刺伤。我使用TOP 1 WITH TIES 作为OP 声明“在一组对话的对话中发送的最后一条消息”。对我来说,这意味着他们正在关注对话中的最新消息。虽然不知道任何具体...
  • 差不多了 :) - 我只需要将时间转换为时间戳 :) - 返回的数据是正确的(行数等)
  • @WebDevelopWolf 当你说时间戳时,你的意思是time
  • 我愿意——我不想要完整的日期,只想要15:30中的时间
【解决方案2】:

当您在查询中有多个表时,总是使用表别名和限定列名。这是你的问题。

以下是如何修复它的示例:

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;

所有 列名都经过适当限定时,您的查询应该会按预期工作。

【讨论】:

    猜你喜欢
    • 2018-09-05
    • 2018-04-20
    • 1970-01-01
    • 2020-02-26
    • 1970-01-01
    • 2019-05-10
    • 1970-01-01
    • 1970-01-01
    • 2017-03-29
    相关资源
    最近更新 更多