Sistema de mensajería privada. Listado del último mensaje de cada conversación
Frecuentes
Visto 1,769 veces
8
Lets say this is the database structure:
SELECT * FROM `pms` where id_to = 1 or id_from = 1
This would return all the messages that he has recived or sent,
So how can I retrieve the last message from cada conversation that the user 1 may have?
PD: I call it conversation when there is one or more messages between two users
operación -Editar-
So given this database content:
We want to get id 4 and 6
3 Respuestas
7
Esto asume id
is an auto-increment column:
SELECT MAX(id) AS id
FROM pms
WHERE id_to = 1 OR id_from = 1
GROUP BY (IF(id_to = 1, id_from, id_to))
Asumiendo que tienes id_from
y id_to
indexed, this variation will most likely perform better because MySQL doesn't know what to do with an OR:
SELECT MAX(id) AS id FROM
(SELECT id, id_from AS id_with
FROM pms
WHERE id_to = 1
UNION ALL
SELECT id, id_to AS id_with
FROM pms
WHERE id_from = 1) t
GROUP BY id_with
Here's how to get the messages for those ids:
SELECT * FROM pms WHERE id IN
(SELECT MAX(id) AS id FROM
(SELECT id, id_from AS id_with
FROM pms
WHERE id_to = 1
UNION ALL
SELECT id, id_to AS id_with
FROM pms
WHERE id_from = 1) t
GROUP BY id_with)
Respondido 28 ago 12, 15:08
3
select pms.* from pms
inner join
(select max(fecha) as max_fecha,
if(id_to<id_from,id_to,id_from) min_id,
if(id_to<id_from,id_from,id_to) max_id
from pms where id_to = 1 or id_from = 1
group by if(id_to<id_from,id_to,id_from),if(id_to<id_from,id_from,id_to)) t
on (if(pms.id_to<pms.id_from,pms.id_to,pms.id_from)=t.min_id)
and (if(pms.id_to<pms.id_from,pms.id_from,pms.id_to)=t.max_id)
and (pms.fecha=t.max_fecha)
Also if id_to and id_from in your table are small enough to prevent overflow in statement (id_to+id_from) here is the simple query:
select pms.* from pms
inner join
(select max(fecha) as max_fecha, id_to+id_from as sum_id
from pms where id_to = 1 or id_from = 1
group by id_to+id_from) t
on ((pms.id_to+pms.id_from)=t.sum_id)
and (pms.fecha=t.max_fecha)
where pms.id_to = 1 or pms.id_from = 1
Respondido 28 ago 12, 17:08
This is showing the last message of each user of each conversation. Its close, but we only want the last message of each conversation - Toni Michel Caubet
@ToniMichelCaubet, is this really the one you're going to use? - marcus adams
yours performe better? the only reason is cause i have to add all the other rows to your query and rename the max(id) as id... @MarcusAdams - Toni Michel Caubet
Works OK! But replace "GROUP BY id_to+id_from" with: "GROUP BY sum_id". And this is redundant: "((pms.id_to+pms.id_from)=t.sum_id)", also "WHERE pms.id_to = 1 or pms.id_from = 1" is a redundancy; remove that as well and the code will be much shorter / efficient. - andreszs
1
Esta consulta debería funcionar:
SELECT a.*
FROM pms a
INNER JOIN (
SELECT id_to, id_from, MAX(fecha) AS fecha
FROM pms
WHERE (id_to = 1 OR id_from = 1)
GROUP BY LEAST(id_to, id_from)
) b
ON a.fecha = b.fecha AND
(a.id_to = b.id_to OR
a.id_from = b.id_from);
Si tiene id
as PRIMARY KEY
and you are logging messages in a chronological order, then it can be further optimized and simplified as:
SELECT a.*
FROM pms a
INNER JOIN (
SELECT MAX(id) AS id
FROM pms
WHERE (id_to = 1 OR id_from = 1)
GROUP BY LEAST(id_to, id_from)
) b
ON a.id = b.id;
Respondido 28 ago 12, 19:08
The following errors were reported:Every derived table must have its own alias - Toni Michel Caubet
ohh ok.. forgot alis for derived table b
. updated query, try now. - Omesh
gosh... The following errors were reported:Column 'id_to' in where clause is ambiguous - Toni Michel Caubet
Now works but is giving the last message of each user of each conversation. Its close, but we only want the last message of each conversation - Toni Michel Caubet
The thing is that this will give 2 messages per conversation, i want only the last one.. - Toni Michel Caubet
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas mysql sql or haz tu propia pregunta.
This seems to work! i will give it a bit of testing and let you know. thanks! - Toni Michel Caubet
@ToniMichelCaubet, another update to return the whole message. - marcus adams
I wouldn't tell.. as you can imagine I am not any master of sql. Plus, my database has very few records.. btw, I am using it ;) - Toni Michel Caubet