SQL查询同一列的多个值在一行中

时间:2017-09-14 17:20:20

标签: mysql sql foreign-keys relational-database

我正在尝试获取一个对话列表以及与其关联的参与者,以及给定用户的最后一条消息。我正在寻找的结果是:

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

以上型号只有一行。我试图获得具有上述结果的所有行。 text列是与该会话关联的最后一条消息。

以下是我的模特:

用户

userId|username|
   87   aester
   89   cester
   96   bester

会话

|conversationId|
      67
      68

消息

| 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

如何查询上述模型以获得所需的结果?

CURRENT UPDATE:

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`;

以上是产生这个我想要的,除了我无法弄清楚如何获取每一行中的最后一条消息:

|  conversationId  |  participants  |
         67           aester,bester
         68              cester

2 个答案:

答案 0 :(得分:0)

如果我正确理解您的问题,您希望将现有查询与Messages表结合使用,以便获得每个会话的最后一条消息。这可以这样做。

首先创建一个子查询来获取每个对话的最后一条消息,如

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; 

现在使用conversation_id列作为连接条件,使用您的查询加入上述子查询。这将填充针对结果的最后一条消息

您的最终查询将如下所示

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`;

答案 1 :(得分:0)

如果您想要一个对话列表,那么我们首先从UserConversations开始,获取每个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.

然后我们找到了每个conversation_id

的最后一条消息
SELECT `conversation_id` , MAX(`messageId`) as `messageId`
FROM Messages1
GROUP BY `conversation_id`;

然后我们将所有东西加在一起:

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`;

<强>输出

enter image description here

注意:我必须将1添加到表名中,因为有些表已经在我进行演示的平台上,并且无法删除它。