简体   繁体   中英

Combine mysql query with sub query results into one PHP array

I have a table that contains events, to list these events I loop through the event table, check the event type and look up it's value in it's specific table with it's eventId.

At the moment this uses one query to get the 20 events and then up to 3 queries to get the data on those events. I currently have it coded procedurally but need to change it so that at the end it just returns the data in array form.

Here's a Pseduo code example of what I need to achieve:

while(eventQuery):

    if commentQueryResult;
        $array .= commentQueryResult;

    if forumPostQueryResult;
        $array .= forumPostQueryResult;

    if uploadItemQueryResult;
        $array .= uploadItemQueryResult;

endwhile;

return $array; // Combined returned results as one array

I will then be able to access the data and just foreach loop through it.

I'm just not sure the best way to combine multiple result sets into an array?

OR you could try and combine them into one query ...

$eventResult = mysql_query(
    'SELECT userevent.event, userevent.eventId, userevent.friendId 
    FROM userevent
    WHERE userevent.userId = 1 OR userevent.friendId = 1 
    ORDER BY userevent.id DESC
    LIMIT 20'
);

while ($eventRow = mysql_fetch_row($eventResult)){

    if($eventRow[0] == 1){

        $result = mysql_fetch_array(mysql_query("
            SELECT forumRooms.id, forumRooms.title                                                                                       
            FROM forumPosts                                                 
            INNER JOIN forumRooms ON forumPosts.`forumTopic` = forumRooms.`id`                                                      
            WHERE forumPosts.id = '$eventRow[1]'"));
    }
    elseif($eventRow[0] == 2){

        $result = mysql_fetch_array(mysql_query("
            SELECT game.id, game.uriTitle, game.title                                                           
            FROM usergamecomment 
            INNER JOIN game ON usergamecomment.`gameId` = game.id
            WHERE usergamecomment.id = $eventRow[1]"));   
    }
    elseif($eventRow[0] == 4){

        $result = mysql_fetch_array(mysql_query("
            SELECT usercomment.comment, UNIX_TIMESTAMP(usercomment.TIME), `user`.id, `user`.username, `user`.activate
            FROM usercomment
            INNER JOIN `user` ON usercomment.`userId` = `user`.id
            WHERE usercomment.id = $eventRow[1]
            AND `user`.activate = 1"));
    }
    elseif($eventRow[0] == 5){

        $result = mysql_fetch_array(mysql_query("
            SELECT game.id, game.title, game.uriTitle 
            FROM game 
            WHERE game.id = $eventRow[1]"));
    }

// Combined Results as array
}

I'm in the process of converting all of these to PDO, that's the next step after working out the best way to minimise this.

Challenge accepted. ;)

Since you are actually only interested in the results inside the while loop, you could try this single query. Due to the LEFT JOINS it might not be faster, pretty much depends on your database. The final $result contains all elements with their respective fields.

$result = array();
$q = 'SELECT userevent.event AS userevent_event, 
      userevent.eventId AS userevent_eventId, 
      userevent.friendId AS userevent_friendId,
      forumRooms.id AS forumRooms_id,
      forumRooms.title AS forumRooms_title,
      game.id AS game_id,
      game.uriTitle AS game_uriTitle,
      game.title AS game_title,
      usercomment.comment AS usercomment_comment, 
      UNIX_TIMESTAMP(usercomment.TIME) AS usercomment_time,
      user.id AS user_id, 
      user.username AS user_username, 
      user.activate AS user_activate,
      g2.id AS game2_id,
      g2.uriTitle AS game2_uriTitle,
      g2.title AS game2_title


    FROM userevent
    LEFT JOIN forumPosts ON forumPosts.id = userevent.eventId
    LEFT JOIN forumRooms ON forumPosts.forumTopic = forumRooms.id
    LEFT JOIN usergamecomment ON usergamecomment.id = userevent.eventId
    LEFT JOIN game ON usergamecomment.gameId = game.id
    LEFT JOIN usercomment ON usercomment.id = userevent.eventId
    LEFT JOIN user ON usercomment.userId = user.id
    LEFT JOIN game g2 ON userevent.eventId = g2.id
    WHERE (userevent.userId = 1 OR userevent.friendId = 1)
      AND userevent.eventId >= (SELECT userevent.eventId 
                WHERE userevent.userId = 1 OR userevent.friendId = 1 
                ORDER BY userevent.id DESC LIMIT 1,20);';

$r = mysql_query($q);

while ( $o = mysql_fetch_row($r) ) {
  switch($o['userevent_event']) {
    case 1: 
      $result[] = array(
    'id' => $o['forumsRooms_id'],
    'title' => $o['forumsRooms_title'],
      );
      break;
    case 2: 
      $result[] = array(
    'id' => $o['game_id'],
    'uriTitle' => $o['game_uriTitle'],
    'title' => $o['game_title'],
      );
      break;
    case 4: 
      $result[] = array(
    'comment' => $o['usercomment_comment'],
    'time' => $o['usercomment_time'],
    'id' => $o['user_id'],
    'username' => $o['user_username'],
    'activate' => $o['user_activate'],
      );
      break;
    case 5: 
      $result[] = array(
    'id' => $o['game2_id'],
    'uriTitle' => $o['game2_uriTitle'],
    'title' => $o['game2_title'],
      );
      break;
  }
}

Note: Eventually, the query has to be edited slightly, I just wrote that out of my head w/o testing. Optimization can surely be done if I'd knew more about the db structure.

Also, this is merely a proof of concept that it can indeed be done with a single query. ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM