【问题标题】:SQL, finding most recent entry in conversation between two peopleSQL,查找两个人之间对话的最新条目
【发布时间】:2012-05-27 19:57:29
【问题描述】:

我有一个表Messages,设置如下:

此表存储人与人之间发送的所有消息,但它需要像 FaceBook 的消息系统。

为此,我的查询需要类似于:

SELECT * FROM Messages WHERE To_User = x OR From_User = x ORDER BY Time DESC

这将按时间顺序获取发送或接收的每条消息“x”,最新消息首先出现。

但是 Facebook 的系统让它有点像论坛,所以我只想要一条消息,其中任何给定的查询结果都涉及到人 y。所以我不希望这种情况发生:

To_User:6 From_User:7 状态:我同意你的留言 时间:12345

To_User:7 To_User:6 状态:你同意我的信息吗? 时间:12344

假设我正在为用户 6 显示消息页面,两条消息都会显示在我当前的系统中。 相反,应该只选择最上面的一条,因为我只想显示用户 6 和 7 之间的最新消息,而不是每条消息。

当然,这通常只要求一个 LIMIT 语句,但我需要能够收到很多消息,但唯一的规则是:

1- 必须是 FROM 或 TO 用户 X 2- 不能选择来自或给用户 Y 的两条消息 3- 选择的消息必须是用户 X 和 Y 之间对话中的最新消息

这真的很难描述,但我希望我已经对它进行了足够详细的描述以提供解决方案。

我考虑过使用 GROUP BY,但我无法考虑到它需要找到一个来自 FROM 或 TO me 而不仅仅是来自或仅来自。

如果问题描述得不够详细,请在投反对票之前告诉我,我会尽力让它更详细一些,但我想不出用什么词来描述需要做的事情显示得足够清楚。

编辑:

这是所需功能的一个重要示例:

假设我向 John Doe 发送了一条消息,然后立即进入我的消息页面,在最顶部会显示

“致 John Doe” “我发送的消息”

但是,如果 John Doe 回复,该条目将不再显示在页面上,它将被我和 John Doe 之间对话中的最新条目替换,因此虽然实际条目仍在数据库中,但它不是'不再显示:

“来自约翰·多伊” “你的消息很有趣”

但如果我之后给 Jane Doe 发了一封邮件,它会推动我和 John Doe 的对话,所以看起来像这样:

“致简·多伊” “你好”

“来自约翰·多伊” “你的消息很有趣”

现在我在这篇文章中提到的第一个查询,结果将是:

“致简·多伊” “你好”

“来自约翰·多伊” “你的消息很有趣”

“致 John Doe” “我发送的消息”

但是,我不想显示我和 John Doe 之间的多个列,但由于我正在查看表格中的两个不同列(From 和两个)来确定我和 John Doe 是否相关,我认为常规的 GROUP BY 语句行不通。

现在,如果 Bob Joe 还给我发了一条消息,它可能看起来像:

“来自鲍勃·乔” “你好”

“致简·多伊” “你好”

“来自约翰·多伊” “你的消息很有趣”

【问题讨论】:

  • 我假设您使用的是 MySQL,对吧?
  • 我无法理解这个问题。 :|限制有什么问题?您能给我们一个真实的用例示例吗?
  • 认为我理解这个问题,但我同意 Cranio 的观点。如果您给出一个实际示例来说明您正在尝试做什么,那么理解您的问题会容易 17 倍。示例输入,预期输出。甚至可以为我们制作一个sqlfiddle
  • 我举个例子,给我一点时间编辑

标签: mysql sql


【解决方案1】:

您可以自联接表并使用外部联接,这样任何“较早”的消息都会“过滤掉”任何“非较早”的消息。

SELECT * FROM Messages main LEFT JOIN Messages earlier
    ON earlier.time < main.time AND 
        (
            earlier.To_User = main.To_User AND earlier.From_User = main.From_User OR  
            earlier.To_User = main.From_User AND earlier.From_User = main.To_User
        )
WHERE (main.To_User = x OR main.From_User = x) AND earlier.id IS NULL
ORDER BY main.Time DESC

【讨论】:

  • 谢谢,我现在就试试这个,如果可行就接受,看起来会的
  • 对不起,我这没有返回任何东西,我已将 x 更改为有效 ID(有消息)并及时更正了未大写的 t(我不确定大写是否重要) .知道为什么吗?
  • @AshleyDavies - 我认为这不起作用的空间不大。你的数据库引擎是什么?如果去掉earlier.id IS NULL 的勾选,你会看到什么数据?您是在使用完全相同的查询,还是将其嵌入到更大的查询中?你如何提供x
  • @AshleyDavies - mysql 中的列名不区分大小写,但在某些操作系统上,表名可能是。关于 PHP 问题,我认为在查询中将 * 替换为 main.* 会有所帮助。也许您甚至必须在 PHP 中打印特定的列。
  • @AshleyDavies - 因为你忘了把 earlier.id IS NULL 放回去。
【解决方案2】:

如果您可以消除出现在“from”或“to”列中的人的复杂性,那么这将是在组中查找最小行的常见问题的一个实例。所以你可以从这个开始:

SELECT id, time, to_user as user
UNION ALL SELECT id, time, from_user as user

然后将该查询的结果用作任何标准minimum row techniques 的输入。

【讨论】:

  • 不幸的是,我无法摆脱他们处于其中一个或另一个,我需要跟踪,以便我知道是谁发送了个人消息
  • 我不是说改变你原来的表结构;我的意思是使用 SELECT 查询的结果作为最小行技术的输入。
  • 啊,误会你的回答了,抱歉。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多