2010-10-03 9 views
2

J'ai deux tables: messages (messages utilisateurs affichés), aime (beaucoup à beaucoup de relations entre les utilisateurs et les messages - il dit que user1 aime message5).SQL - Ordre par colonne à partir de deux tables

messages 
--------- 
id, id_user, message, created_at 

likes 
----- 
id_user, id_message, created_at 

Si j'envoie un message, il va à la table des messages. Si j'aime le message de quelqu'un, un nouvel enregistrement sera créé dans la table des likes (is_user = me, id_message = message que j'aime).

Le problème est, je voudrais montrer l'histoire de mes actions = messages et aime ensemble dans une liste commandé par "created_at".

Quelque chose comme:

- 1/1/2010 i sent message "aaa" 
- 2/1/2010 i sent message "bbb" 
- 3/1/2010 i liked somebodys's message "ccc" 
- 4/1/2010 i send message "ddd" 

EDIT Et en plus, je veux aussi des informations sur l'état que j'ai aimé:

- 3/1/2010 i liked somebodys's message **"ccc"** 

Comment faire cela?

Répondre

6

Ce serait une bonne idée de créer une nouvelle table appelée 'actions' où ajouter un message ou aimer un message sont recrodés dans cette table, alors il est simple d'obtenir ce que vous voulez en interrogeant cette table.

Si vous ne pouvez pas faire cela, alors vous utilisez votre schéma existant par UNIONing les données de chaque table et l'interrogation de la table résultant, mais il ne sera pas aussi efficace que sur un indice created_at ne peut pas être utilisé:

SELECT * FROM 
(
    SELECT 1 AS type, id, id_user, message, created_at FROM messages 
    UNION ALL 
    SELECT 2 AS type, NULL, id_user, id_message, created_at FROM likes 
) T1 
ORDER BY created_at 

Ajoutez des jointures pour obtenir des informations relatives au message que vous avez aimé, telles que le nom d'utilisateur de l'expéditeur du message et le texte du message. Il est généralement préférable de convertir ces informations en chaînes au niveau de l'application afin de réduire le transfert de données inutile entre votre serveur de base de données et votre application.

Si vous vraiment voulez faire dans la base de données, vous pouvez utiliser CONCAT pour construire les cordes:

SELECT messagetext 
FROM 
(
    SELECT 
     created_at, 
     CONCAT('I sent message "', message, '"') AS messagetext 
    FROM messages 
    WHERE id_user = 1 
    UNION ALL 
    SELECT 
     likes.created_at, 
     CONCAT('I liked ', messages.id_user ,'\'s message "', messages.message, '"') 
    FROM likes 
    JOIN messages 
    ON likes.id_message = messages.id 
    WHERE likes.id_user = 1 
) T1 
ORDER BY created_at 

Résultat:

 
I sent message "aaa" 
I sent message "bbb" 
I liked 2's message "ccc" 
I sent message "ddd" 

Notez que le user_id apparaît à la place de l'identifiant. Si vous voulez le nom d'utilisateur, vous devrez également joindre à la table des utilisateurs (cette table n'a pas été montrée dans votre question, mais je suppose que vous en avez un).

+0

Merci Mark. Je n'ai pas besoin de toutes les chaînes, c'est la responsabilité de l'application. J'ai juste besoin du texte du message que j'ai aimé et qui pourrait être fait très facilement en utilisant des jointures. – PetrB

+0

J'ai décidé d'aller de l'avant en créant la nouvelle table 'actions' mais je suis coincé avec le schéma de base de données. Pour le moment, la table des actions a des colonnes action_id, created_at, discriminator. Quoi d'autre dois-je mettre là et comment l'interroger? – PetrB

+0

@PetrB: Cela semble être un bon début. Vous n'avez pas besoin de dupliquer les données des autres tables de cette table. –

0
SELECT .... 
FROM 
(
    SELECT MSGS. 
     ...... 
     MSGS.created_at 
    FROM MSGS 
    WHERE MSG.id_user = me 
    UNION 
    SELECT LIKES. 
     .......... 
     LIKES.created_at 
    FROM MSGS, LIKES 
    WHERE MSGS.id_message = LIKES.id_message 
     AND MSGS.id_user = me 
) A 
ORDER BY A.created_at 
Questions connexes