如何选择每组最近的一个? (尝试从每个人中选择最近的消息并将其链接到对话)

[英]How do I select one most recent of each group? (Trying to select the most recent message from each person and make it link to the conversation)


My "messages" table has the following fields:

我的“消息”表包含以下字段:

messageid, idto, idfrom, content, and timeSent.

messageid,idto,idfrom,content和timeSent。

I want my mailbox page to group all of the mails from each individual person (idfrom) and only print the most recent one from each of them. The idea here is that the most recent "conversation" will be at the top of the users mailbox.

我希望我的邮箱页面可以对来自每个人(idfrom)的所有邮件进行分组,并且只打印每个邮件中的最新邮件。这里的想法是,最近的“对话”将位于用户邮箱的顶部。

I have been googling for hours trying to find a solution. Some claim you need a NATURAL JOIN. Some claim LEFT JOIN. Some have a bunch of frustrating symbols, or "aliases" with no explanation as to where they are defined in your script, e.g. n1.* c2.*.

我一直在谷歌搜索数小时试图寻找解决方案。有些人声称你需要一个自然的联接。有些人声称LEFT JOIN。有些人有一些令人沮丧的符号,或“别名”,没有解释他们在你的脚本中定义的位置,例如: n1。* c2。*。

I have already tried GROUP BY, but it draws randomly (sometimes grabbing older messages and not the most recent one). My current query is below:

我已经尝试过GROUP BY,但它会随机绘制(有时会抓取较旧的消息而不是最新的消息)。我目前的查询如下:

"SELECT * FROM messages WHERE idto=$id ORDER BY timeSent DESC LIMIT 100"

“SELECT * FROM messages WHERE idto = $ id ORDER BY timeSent DESC LIMIT 100”

Again, using "GROUP BY" will sometimes omit the most recent mail, which is the opposite of what I want.

同样,使用“GROUP BY”有时会省略最近的邮件,这与我想要的相反。

EDIT: Problem Solved (by not using any additional SQL): Instead of modifying my query, I went with good old PHP and reduced the execution time by a significant amount. Here's how:

编辑:解决了问题(通过不使用任何其他SQL):我没有修改我的查询,而是使用了旧的PHP并将执行时间大幅减少了。这是如何做:

  1. Before the "fetch array" loop, I created a variable and made it an empty array ($var = array();)

    在“fetch数组”循环之前,我创建了一个变量并使其成为一个空数组($ var = array();)

  2. After that, I made an if statement at the beginning of the FETCH_ARRAY() loop and enclosed all of my previous code into it. (if(!in_array($q['idfrom'], $var))). So, if my user's ID is not already in the array, it will proceed. If it's already there, it will skip on and keep moving through the loop.

    之后,我在FETCH_ARRAY()循环的开头创建了一个if语句,并将我之前的所有代码都包含在其中。 (if(!in_array($ q ['idfrom'],$ var)))。因此,如果我的用户的ID不在数组中,它将继续。如果它已经存在,它将跳过并继续在循环中移动。

  3. At the end of a successful loop (the one that the if statement allowed to pass), I added "array_push($var, $q['idfrom']);"

    在成功循环结束时(if语句允许通过的循环),我添加了“array_push($ var,$ q ['idfrom']);”

Meaning, the user's ID is added to the array so that if one of their messages are selected again, the loop skips it.

这意味着,用户的ID将添加到数组中,以便在再次选择其中一条消息时,循环会跳过它。

Viola, it successfully prints the most recent mail from each user with only 3-5 lines of additional PHP code. It's also very modifiable for other purposes as long as your desired condition draws the correct table first, as it will ignore the rest. Make sure your ordering is correct.

Viola,它只需3-5行额外的PHP代码就能成功打印每个用户的最新邮件。只要你想要的条件首先绘制正确的表格,它也可以用于其他目的,因为它会忽略其余的。确保您的订购正确无误。

I would like to thank everyone for the help and I hope this will save a lot of people a lot of time like it did for me. It was my initial thought, but I felt that using a query may have been the "right" way to do it and decided to ask here.

我要感谢大家的帮助,我希望这会为很多人节省很多时间。这是我最初的想法,但我觉得使用查询可能是“正确”的方式,并决定在这里问。

2 个解决方案

#1


0  

You have to make use of a temp table which pre sorts your messages by toId and timeSent

您必须使用临时表,该表通过toId和timeSent对您的消息进行排序

Then join this temp table to messages

然后将此临时表连接到消息

For instance, create a table with data

例如,创建一个包含数据的表

CREATE TABLE messages
(
messageId integer,
idTo integer,
idFrom integer,
timeSent datetime,
content varchar(255)
);

insert into messages values (1,11,1,'2013-07-11','first message to user 11');
insert into messages values (2,12,1,'2013-07-03','fist message to user 12');
insert into messages values (3,11,1,'2013-07-12','second message to user 11');
insert into messages values (4,12,1,'2013-07-05','second message to user 12');
insert into messages values (5,13,1,'2013-07-10','second message to user 13');
insert into messages values (6,13,1,'2013-07-09','first message to user 13');

Then query the two joined tables

然后查询两个连接的表

CREATE TEMPORARY TABLE t1 AS (SELECT idTo, max(timeSent) as timeSent from messages group by idTo);

select m.idFrom, m.idTo, m.timeSent, m.content from t1
join messages m on t1.idTo = m.idTo
and t1.timeSent = m.timeSent;

... and get this reesult

......得到这个结果

idFrom        idTo      timeSent                content
1             11        2013-07-12 00:00:00     second message to user 11
1             12        2013-07-05 00:00:00     second message to user 12
1             13        2013-07-10 00:00:00     second message to user 13
  • Jeff Weiss

#2


0  

You can do this directly with a query. Here is an example of one:

您可以直接使用查询执行此操作。这是一个例子:

select m.*
from messages m
where m.timeSent = (select max(m2.timeSent) from message m2 where m2.idFrom = m.idFrom)

This will have reasonable performance if you have an index on `messages(idFrom, timeSent).

如果你有`messages(idFrom,timeSent)的索引,这将有合理的性能。

关注微信公众号

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2013/08/08/c08303d48a955835bf0b24d21eb7d76a.html



 
粤ICP备14056181号  © 2014-2020 ITdaan.com