2017-09-14 2 views
0

J'essaie d'obtenir une liste de conversations et les participants associés à une seule ligne avec le dernier message pour un utilisateur donné. Le résultat que je cherche est le suivant:SQL requête plusieurs valeurs de même colonne dans une seule ligne

**| conversationId | participants | text | timestamp |** 
      67   aester,bester Hello 00:00:00 

Le modèle ci-dessus est juste une ligne. J'essaie d'obtenir toutes les lignes avec le résultat ci-dessus. La colonne de texte est le dernier message associé à cette conversation.

Voici mes modèles:

utilisateurs

userId|username| 
    87 aester 
    89 cester 
    96 bester 

Conversations

|conversationId| 
     67 
     68 

Messages

| messageId | text | timestamp | conversation_id | user_id 
    41  Hello  00:00:00   67    87 
    42  Hey  00:00:00   68    89 

UserConversations

| id | conversation_id | user_id 
    3   67   87 
    4   67   96 
    5   68   89 

Comment puis-je interroger les modèles ci-dessus pour obtenir le résultat souhaité?

MISE A JOUR EN COURS:

SELECT conversations.`conversationId` as conversationId, 
GROUP_CONCAT(users.`username`) as participants FROM users 
LEFT JOIN user_conversations 
ON users.`userId` = user_conversations.`user_id` 
LEFT JOIN conversations 
ON user_conversations.`conversation_id` = 
conversations.`conversationId` 
WHERE EXISTS (SELECT * FROM user_conversations WHERE 
user_conversations.user_id = 87) 
GROUP BY conversations.`conversationId`; 

Ce qui précède est la production de ce qui est ce que je veux, sauf que je ne peux pas savoir comment obtenir les derniers messages de chaque ligne également:

| conversationId | participants | 
     67   aester,bester 
     68    cester 
+1

check [** GROUP_CONCAT() **] (https://www.w3resource.com/mysql/aggregate-functions-and-grouping/aggregate-functions-and-grouping-group_concat.php) –

+0

J'ai essayé en utilisant GROUP_CONCAT mais il renvoie tous les participants sur la même ligne même s'ils n'appartiennent pas à la conversation – samuscarella

+0

Montrez-nous le schéma db, les exemples de données, la sortie actuelle et attendue. \t S'il vous plaît lire [** How-to-Ask **] (http://stackoverflow.com/help/how-to-ask) \t \t Et voici un bon endroit pour [** START **] (http://spaghettidba.com/2015/04/24/how-to-post-at-sql-question-on-a-public-forum/) pour apprendre comment améliorer la qualité de vos questions et obtenir de meilleures réponses. \t [** Comment créer un exemple minimal, complet et vérifiable **] (http://stackoverflow.com/help/mcve) –

Répondre

0

Si vous voulez une liste de conversations puis d'abord, nous commençons par UserConversations pour obtenir la liste des participants pour chaque conversation_id

SELECT uc.`conversation_id`, 
     GROUP_CONCAT(u.`username`) as participants  
FROM UserConversations1 uc 
JOIN Users1 u 
    ON uc.`user_id`= u.`userId` 
GROUP BY `conversation_id` 
HAVING COUNT(IF(uc.`user_id` = 87, 1, NULL)) > 0; 
    -- This check if the user in on the conversation. 

Ensuite, nous avons trouvé ce qui était le dernier message pour chaque conversation_id

SELECT `conversation_id` , MAX(`messageId`) as `messageId` 
FROM Messages1 
GROUP BY `conversation_id`; 

Puis nous rejoignons tout ensemble:

SQL DEMO

SELECT conversation.`conversation_id`, 
     conversation.`participants`, 
     m.text, 
     m.timestamp 
FROM ( SELECT uc.`conversation_id`, 
       GROUP_CONCAT(u.`username`) as `participants`  
     FROM UserConversations1 uc 
     JOIN Users1 u 
      ON uc.`user_id`= u.`userId` 
     GROUP BY `conversation_id` 
     HAVING COUNT(IF(uc.`user_id` = 87, 1, NULL)) > 0) as conversation 
JOIN (SELECT `conversation_id` , MAX(`messageId`) as `messageId` 
     FROM Messages1 
     GROUP BY `conversation_id`) as last_message 
    ON conversation.`conversation_id` = last_message.`conversation_id` 
JOIN Messages1 m 
    ON m.`messageId` = last_message.`messageId`; 

SORTIE

enter image description here

NOTE: Je dois ajouter 1 aux noms de table parce que certaines tables étaient déjà la plate-forme où j'ai fait la démo, et pourrait Ne le laissez pas tomber.

+0

Merci! Cela semble fonctionner. – samuscarella

0

Si je comprends votre question correctement, vous souhaitez joindre votre requête existante avec la table Messages de telle sorte que vous obtenez le dernier message pour chaque conversation. Cela peut être fait comme ça.

d'abord créer un sous-requête pour obtenir dernier message pour chaque conversation comme celui-ci

select message_id as last_message_id, text as last_text, conversation_id, user_id, max(timestamp) from   
(select * from `Messages` 
order by conversation_id, timestamp desc)q 
group by conversation_id; 

maintenant se joindre à la sous-requête ci-dessus avec votre requête en utilisant la colonne conversation_id comme condition de jointure.Ce renseignera dernier message contre votre résultat

Votre requête finale ressemblera à ceci

SELECT conversations.`conversationId` as conversationId, 
GROUP_CONCAT(users.`username`) as participants FROM users 
LEFT JOIN user_conversations 
ON users.`userId` = user_conversations.`user_id` 
LEFT JOIN conversations 
ON user_conversations.`conversation_id` = 
conversations.`conversationId` 
WHERE EXISTS (SELECT * FROM user_conversations WHERE 
user_conversations.user_id = 87) 
LEFT JOIN 
(select message_id as last_message_id, text as last_text, conversation_id, user_id, max(timestamp) from   
(select * from `Messages` 
order by conversation_id, timestamp desc)q 
group by conversation_id) subquery 
on conversations.`conversationId` = subquery.`conversation_id` 
GROUP BY conversations.`conversationId`;