3

我有一个运行良好的聊天系统,但我刚刚意识到的消息列表会拉取每个人的每条消息,然后显示最后一个结果,这显然是对服务器的巨大资源浪费和压力,每个用户只返回一个结果。

这是检索消息列表的查询,然后有一个 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 查询中执行此操作。

4

2 回答 2

2

假设 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]'
于 2013-10-22T01:46:11.213 回答
0

在使用联接的情况下,您的查询应如下所示:

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

显然它还没有经过测试,你绝对应该阅读这个来确定使用哪个连接。

于 2013-10-22T01:45:18.443 回答