>我有一个运行良好的聊天系统,但是我刚刚意识到的消息列表会拉取每个人的每条消息,然后显示最后的结果,这显然是对资源的巨大浪费,并且每个用户只返回一个结果。
这是检索消息列表的查询,之后有一个 while 循环清理数组以仅显示每个用户的最新消息,我知道有一种更好的方法来使用 JOIN 执行此操作,但我无法理解它。
$result = dbconstruct("SELECT messages.id, messages.msgfrom, messages.msg,
messages.active, messages.replied, users.username, users.online, users.admin,
users.imagename FROM messages, users WHERE msgto='$_SESSION[id]'
AND users.id=msgfrom ORDER by messages.id DESC");
我已经浏览了其他答案,但如前所述,发现很难掌握连接技术。
更新
我不认为我已经很好地解释了我需要什么。目前我运行上面的查询,返回大约 2000 个结果,然后使用它将每个用户消息过滤为一条消息。
$clean = array(); while($result->fetch_assoc()) { if(in_array($result[msgfrom],
$clean)) { }
else { //print message }
$usercheck = array_push($clean, $result[msgfrom]); }
这会很好地显示消息列表,并且仅显示来自每个用户的最后一条消息,但这是一个非常糟糕的方法。在 SQL 查询中必须有一种方法可以执行此操作。
假设 message.id auto_incremented,则 MAX 是最新的。否则,如果您有一列作为时间戳,则可以使用它并应用相同的原则。
我认为在 php 中复制您正在尝试的内容的最准确形式是仅选择来自某人的最新消息(子查询)并将其与您想要的输出查询连接起来。我认为它会返回您所期望的:
SELECT m.id,
m.msgfrom,
m.msg,
m.active,
m.replied,
u.username,
u.online,
u.admin,
u.imagename
FROM messages m
INNER JOIN users u ON u.users.id = m.msgfrom
INNER JOIN (SELECT MAX(id) as id, msgfrom
FROM messages
GROUP BY msgfrom
) m2
ON m2.id = m.id AND m2.msgfrom = m.msgfrom
WHERE messages.msgto = '$_SESSION[id]'
在使用联接的情况下,查询应如下所示:
SELECT
messages.id,
messages.msgfrom,
messages.msg,
messages.active,
messages.replied,
users.username,
users.online,
users.admin,
users.imagename
FROM
messages
INNER JOIN
users
ON
users.id = messages.msgfrom
WHERE
msgto='$_SESSION[id]'
ORDER by
messages.id
DESC
显然它还没有经过测试,你绝对应该阅读一下这篇文章,以确定使用哪个联接。