2009-07-30 19 views
6

tengo tres cuadros básicos:MySQL seleccione Unir 3 Tablas

tblUsers: 

    usrID  usrFirst  usrLast 
     1  John   Smith 
     2  Bill   Jones 
     3  Jane   Johnson 

pm_data: 

id  date_sent    title   sender_id thread_id   content 
2 2009-07-29 18:46:13  Subject 1   1   111  Message 2! 
3 2009-07-29 18:47:21  Another Subject  1   222  Message 3! 

pm_info: 

id thread_id receiver_id is_read 
1  111   2   0 
2  111   3   0 
3  222   2   0 
4  222   3   0 

En esencia, lo que estoy tratando de hacer es crear una bandeja de entrada.

Por lo tanto, si usrID 2 (Bill Jones) abre su bandeja de entrada, verá que tiene 2 mensajes no leídos (de ahí la columna 'is_read') (hilos # 111 y # 222).

Básicamente, necesito saber cómo configurar mi declaración SELECT para UNIR las tres tablas (la relación entre pm_data y pm_info genera la información del mensaje, mientras que la relación entre tblUsers y pm_data genera el 'nombre para mostrar' de el remitente), para mostrar el hilo más reciente (¿por marca de tiempo?) en la parte superior.

Así, veríamos algo similar:

<?php $usrID = 2; ?> 

<table id="messages"> 
    <tr id="id-2"> 
    <td> 
    <span> 
    From: John Smith 
    </span> 
    <span>2009-07-29 18:47:21</span> 
    </td> 
<td> 
<div>Another subject</div> 
</td></tr> 
<tr id="id-1"> 
<td> 
    <span> 
    From: John Smith 
    </span> 
    <span>2009-07-29 18:46:13</span> 
</td> 
<td> 
    <div>Subject 1</div> 
</td></tr> 
</table> 

Esperamos que esto tiene sentido! ¡Gracias por cualquier ayuda!

EDIT: Aquí está mi respuesta final:

seguí el consejo de LC, e hizo la relación entre las dos tablas basadas en ID (añade una columna llamada 'message_id' a pm_info).

Entonces, ajustado la declaración de MySQL en torno a un poco para llegar a esto:

SELECT pm_info.is_read, sender.usrFirst as sender_name, 
pm_data.date_sent, pm_data.title, pm_data.thread_id 
FROM pm_info 
INNER JOIN pm_data ON pm_info.message_id = pm_data.id 
INNER JOIN tblUsers AS sender ON pm_data.sender_id = sender.usrID 
WHERE pm_data.date_sent IN(SELECT MAX(date_sent) FROM pm_data WHERE pm_info.message_id = pm_data.id GROUP BY thread_id) AND pm_info.receiver_id = '$usrID' ORDER BY date_sent DESC 

Esto parece funcionar para mí (hasta ahora).

Respuesta

9

Necesitará dos uniones. Algo parecido a lo siguiente debería ayudarle a empezar (aunque yo no entiendo 100% la relación entre pm_data y pm_info):

SELECT pm_info.is_read, sender.usrFirst + ' ' + sender.usrLast as sender_name, 
    pm_data.date_sent, pm_data.title, pm_data.thread_id 
FROM pm_info 
INNER JOIN pm_data ON pm_info.thread_id = pm_data.thread_id 
INNER JOIN tblUsers AS sender ON pm_data.sender_id = tblUsers.usrID 
WHERE pm_info.receiver_id = @USER_ID /*in this case, 2*/ 
ORDER BY pm_data.date_sent DESC 

Asumo la relación entre pm_data y pm_info es el ID del tema. Si no es así, deberías poder ajustar lo anterior a lo que necesites. También he ordenado por fecha enviada aquí, pero no mantendrá los hilos juntos. No estoy seguro de si desea mantenerlos juntos o no por la forma en que formuló su pregunta.


Si desea mantener los hilos juntos, tendrá una consulta más complicado:

SELECT pm_info.is_read, sender.usrFirst + ' ' + sender.usrLast as sender_name, 
    pm_data.date_sent, pm_data.title, pm_data.thread_id 
FROM pm_info 
INNER JOIN pm_data ON pm_info.thread_id = pm_data.thread_id 
INNER JOIN tblUsers AS sender ON pm_data.sender_id = tblUsers.usrID 
INNER JOIN (SELECT thread_id, MAX(date_sent) AS max_date 
      FROM pm_data 
      GROUP BY thread_id) AS most_recent_date 
      ON pm_data.thread_id = most_recent_date.thread_id 
WHERE pm_info.receiver_id = @USER_ID /*in this case, 2*/ 
ORDER BY most_recent_date.max_date DESC, pm_data.thread_id, 
    pm_data.date_sent DESC 

Esta consulta utiliza un subselección para encontrar la fecha más reciente modificado para cada hilo, a continuación, ordena por esto primero.

+0

Gracias lc, por su respuesta. Tu complicada consulta es definitivamente la dirección a la que me dirijo. No arroja ningún error, pero está haciendo un par de cosas: 1) Todavía muestra todas las partes del hilo (incluso los artículos enviados por el usuario relacionados con el hilo) y 2) Lo muestra por duplicado. Avíseme si necesita que sea más explícito. Gracias. – Dodinas

+0

@Dodinas 1) Mostrará todas las partes del hilo. Si no desea mostrar todo, tendrá que pensar qué es exactamente lo que desea filtrar y agregarlo a la cláusula WHERE. También podría haber más en la relación entre 'pm_data' y' pm_info' que me falta, porque todo lo que tengo que seguir ahora es la identificación del hilo ... 2) ¿Puedes publicar un poco más de las tablas? contenidos para que pueda ver dónde podría estar yendo mal? INNER JOINs no debería producir ninguna fila por duplicado. También es posible que su error esté en el PHP después de ejecutar la consulta ... –

+0

@lc: Gracias por la respuesta. Básicamente, no creo que el problema sea con PHP. Sin embargo, podría ser un problema con la forma en que mi db está estructurado. Básicamente, lo que publique son las tablas con las que estoy trabajando. El 'thread_id' es lo único que relaciona las dos tablas. Tal vez necesito hacer un cambio en mi estructura db? – Dodinas

3

Para obtener la lista de mensajes para un usuario, junto con quién y cuándo lo enviaron, se puede utilizar la siguiente consulta:

select 
    s.usrFirst + ' ' + s.usrLast as SenderName, 
    m.Title, 
    m.DateSent, 
    i.IsRead 
from 
    tblUsers r 
    inner join pm_info i on 
     r.receiver_id = i.receiver_id 
    inner join pm_data m on 
     i.thread_id = m.thread_id 
    inner join tblUsers s on 
     m.sender_id = s.userID 
where 
    r.usrid = @id 

Esto se aprovecha del hecho de que puede unirse a una mesa a sí mismo (aquí, tblUsers aparece dos veces: una para el destinatario y otra para el remitente).

Si desea ver solo mensajes no leídos, puede poner and i.IsRead = 0 en la cláusula where.