I had the following code, which uses 2 queries to get the friends list.
<?php
$getFriendStatement = <<<EOS
SELECT DISTINCT u.username
FROM users AS u
INNER JOIN test_friends AS f on u.Id = f.user_id
WHERE f.friend_id = ?
&& f.active=1
EOS;
$getFriendQuery = $mysqli->prepare($getFriendStatement);
$getFriendQuery->bind_param('i', $userID);
$getFriendQuery->execute() or die ($mysqli->error);
$getFriendResult = $getFriendQuery->get_result();
$friendName = "";
while ($getFriendFetch = $getFriendResult->fetch_assoc()) {
$friendName .= $getFriendFetch['username'] . ", ";
}
$getFriendStatement = <<<EOS
SELECT u.username
FROM users AS u
INNER JOIN test_friends AS f ON u.id = f.user_id
WHERE (f.friend_id = ? AND active=1)
OR (f.user_id = ? AND active=1)
EOS;
$getFriendQuery = $mysqli->prepare($getFriendStatement);
$getFriendQuery->bind_param('ii', $userID, $userID);
$getFriendQuery->execute() or die ($mysqli->error);
$getFriendResult = $getFriendQuery->get_result();
while ($getFriendFetch = $getFriendResult->fetch_assoc()) {
$friendName .= $getFriendFetch['username'] . ", ";
}
if (!empty($friendName)){
echo "Your friends: " . $friendName ;
} else {
echo "You do not have any friends yet";
}
?>
Is there a way to execute just 1 query to retrieve all friends?
Schema information: the above relies on two tables, users
and test_friends
:
CREATE TABLE users (
`id` int(11),
`username` varchar(256)
);
CREATE TABLE test_friends (
`user_id` int(11),
`friend_id` int(11),
`active` tinyint,
FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
ON UPDATE CASCADE ON DELETE CASCADE,
FOREIGN KEY (`friend_id`) REFERENCES `users` (`id`)
ON UPDATE CASCADE ON DELETE CASCADE
);
You should be able to do a union to do both queries in one. Your SQL will look like this:
SELECT U.username
FROM users AS U
INNER JOIN test_friends AS F
ON U.Id = F.user_id
WHERE F.friend_id = '{$userID}'
AND F.active = 1
UNION
SELECT u.username
FROM users u
INNER JOIN test_friends f
ON u.id = f.user_id
WHERE ( f.friend_id = '{$userID}'
AND active = 1 )
OR ( f.user_id = '{$userID}'
AND active = 1 )
It will also remove duplicates for you automatically, as if you included DISTINCT on the whole lot. (You do "UNION ALL" if you don't want that.)
Also, if you want to order the results, add "ORDER BY 1 ASC" on the end. You can only use result set column numbers in the ORDER BY clause with unions.
Union queries only work if the number and types of the columns returned in the result set by each sub-query are the same.
Aside: Your first query appears to be a subset of the second query, so you really only need to so the second query. I've left it as is as a demonstration of how to do unions, but you don't really need to in this case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With