【问题标题】:How to combine sql select queries for this situation?这种情况如何结合sql select查询?
【发布时间】:2011-10-12 04:35:28
【问题描述】:

我正在用 php/mysql 编写一个聊天应用程序

我有 3 个表:user, roomroom_participant 具有这些结构:

user: id, username
room: id, title
room_participant: room_id, user_id

现在我想获取所有房间的列表以及每个房间中所有参与者的列表。

到目前为止,我只是从房间表中选择所有房间并遍历所有房间并从每个条目中选择用户信息,这是非常低效的。

有没有办法将所有这些选择组合成一个选择查询?

【问题讨论】:

    标签: mysql select


    【解决方案1】:

    不经过测试不确定,但试一试:

    SELECT
       room.*, 
       user.* 
    FROM room 
      JOIN room_participant ON room_id = room_participant.id
      JOIN user ON room_participant.user_id = user.id
    ORDER BY room.id
    

    要对房间进行重复数据删除,请使用GROUP_CONCAT()

    更新 GROUP_CONCAT()修改为返回id|username

    SELECT
       room.id, room.name
       GROUP_CONCAT(CONCAT(user.id,'|',user.username)) AS userlist 
    FROM room 
      JOIN room_participant ON room_id = room_participant.id
      JOIN user ON room_participant.user_id = user.id
    GROUP BY room.id, room.name
    ORDER BY room.id
    

    GROUP_CONCAT生成的userlist作为id|name,id|name,id|name,你可以使用PHP explode()来分隔它们。

    // Split the list on the commas
    $users = explode(",", $userlist);
    
    
    $final_users = array();
    // Then split each on the `|`
    foreach ($users as $user) {
      $split_user = explode("|", $user);
    
      // Append each as a new associative array to $final_users
      $final_users[] = array('id' => $split_user[0], 'username' => $split_user[1]);
    }
    
    // Now you have an array of users as id, username
    var_dump($final_users);
    

    【讨论】:

    • 您的第二次加入有错字:ON room_participant.user_id
    • 嗨,感谢您的回答,它可以工作,但是当该房间有超过 2 个参与者时,查询会返回具有相同 room_id 的多条记录。我可以对记录中的用户条目进行分组(类似于房间记录字段中的用户数组)吗?
    • @Peacemoon 尝试使用GROUP_CONCAT() 进行上述添加。它只会返回用户名,而不是用户名和用户 ID
    • @Michael:那么是否可以同时获取用户列表的用户名和 ID?
    • @Michael:我最终得到了对用户名和 id 都使用 GROUP_CONCAT 的解决方案。然后我可以稍后使用 php 代码操作列表。感谢您的帮助
    【解决方案2】:

    您可能希望执行两个查询,然后在使用 MySQL 的任何内容中进行匹配,例如PHP。

    这两个:

    SELECT id, title
      FROM room;
    
    SELECT rp.room_id, rp.user_id, u.username
      FROM room_participant AS rp
           INNER JOIN user as u ON rp.user_id = u.id;
    

    或者这两个:

    SELECT id, username
      FROM user;
    
    SELECT rp.room_id, rp.user_id, r.title
      FROM room_participant AS rp
           INNER JOIN room as r ON rp.user_id = r.id;
    

    哪两个查询有意义取决于您对信息的真正用途。

    您可以更进一步,分别选择所有三个:

    SELECT *
      FROM room;
    
    SELECT *
      FROM user;
    
    SELECT *
      FROM room_participant;
    

    注意:最好说明列,而不是使用“*”,以防将来您对这些查询并不真正感兴趣的新列被添加到表中。

    显然,您必须在使用 MySQL 的任何内容中匹配所有内容,例如php。您可以根据所选信息创建房间和用户列表,然后将它们与以下内容匹配:

    // Use MySQL to populate $roomList from database, then do...
    foreach ($roomList as $room)
    {
        $id    = $room['id'];
        $title = $room['title'];
    
        $this->roomList[$id] = new Room($id, $title);
    }
    
    // Use MySQL to populate $userList from database, then do...
    foreach ($userList as $user)
    {
        $id       = $user['id'];
        $username = $user['username'];
    
        $this->userList[$id] = new User($id, $username);
    }
    
    // Use MySQL to populate $roomParticipantList from database, then do...
    foreach ($roomParticipantList as $roomParticipant)
    {
        $room = $this->roomList[$roomParticipant['room_id']];
        $user = $this->userList[$roomParticipant['user_id']];
    
        // You could do one/both of these, depending on requirements.
        $room->enterUser($user);
        $user->joinRoom($room);
    }
    

    【讨论】:

    • 感谢您的详细解答。我认为只用 1 个查询就完成所有事情真的很困难。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-25
    • 2011-01-09
    • 1970-01-01
    • 2014-06-26
    • 2018-01-25
    • 1970-01-01
    • 2020-10-30
    相关资源
    最近更新 更多