Reputation: 190
From my application, I send a list of users that I want to search the group they are subscribed:
$selectedUsers = ["John", "Carlos", "Anna", "Julia"]
I have in my database many different groups with many different users in each of them:
$football = ["**John**" ,"**Carlos**" ,"Daniel" ,"Rob" ,"Frank" ,"Bob"]
$cooking = ["**John**" , "**Anna**" , "**Julia**" , "Claudia" , "Rob" , "Adriana"]
$startups = ["**John**", "**Carlos**", "**Anna**", "**Julia**", "Rob", "Adriana"]
The output I want to have is the sorted list of groups with the amount of the selectedUsers in it:
$returnArray[0] = $startups //4 users inside group
$returnArray[1] = $cooking //3 users inside group
$returnArray[2] = $football //2 users inside group
Here is the code I have so far, but the loop I'm using is based on the group_id I've stored and I want to change that:
<?php
//fetch groups with users
$returnValue = array();
$groupUsersNumber = 0;
$selectedUsers = htmlentities($_REQUEST["selectedUsers"]);
$lastGroupID = htmlentities($_REQUEST["lastGroupID"]); //remove
if($lastGroupID == ""){
$lastGroupID = getLastGroupID();
$lastGroupID = $lastGroupID + 1;
}
if($selectedUsers == ""){
//return all groups ordered by ID desc
$group = getGroupWithID($lastGroupID);
} else{
$usersArray = explode(', ', $selectedUsers);
$foundGroup = false;
while($foundGroup == false){
$group = getGroupWithID($lastGroupID);
$fetchedGroupUsers = explode(', ', $group["users"]);
for($i = 0; $i < count($usersArray); $i++){
if(in_array($usersArray[$i], $fetchedGroupUsers)){
$foundGroup = true;
break;
} else{
$lastGroupID = $group["group_id"];
}
}
}
}
for($i = 0; $i < count($usersArray); $i++){
if(in_array($usersArray[$i], $fetchedGroupUsers)){
$groupUsersNumber = $groupUsersNumber + 1;
}
}
if(empty($group))
{
$returnValue["status"]="403";
$returnValue["message"]="No more groups with that users.";
echo json_encode($returnValue);
return;
} else{
$returnValue=$group;
$returnValue["groupUsersNumber"]=$groupUsersNumber;
}
echo json_encode($returnValue);
?>
Is there any other way to have a better/ more efficient way to search into my database? Appreciated!
Upvotes: 1
Views: 173
Reputation: 21513
You appear to be mixing up php and mysql, and it would be better to redesign your database.
However as a basic idea you can do roughly what you want in MySQL. It is not nice, and not efficient but something like this:-
SELECT a.group_description ,
GROUP_CONCAT(b.wanted_name)
FROM some_table a
LEFT OUTER JOIN
(
SELECT "John" AS wanted_name UNION SELECT "Carlos" UNION SELECT "Anna" UNION SELECT "Julia"
) b
ON FIND_IN_SET(b.wanted_name, a.group_users)
GROUP BY a. group_description
Upvotes: 1
Reputation: 5119
It seems that your database is not normalized. A normalized database may be the more efficient way. Do not store users in a describing varchar. Instead establish a many to many relation.
Beside that the FilterIterator class of PHP is something for you. It is reusable and a bit more efficient at iterating over arrays.
Here 's a short example.
class NameFilterIterator extends FilterIterator {
protected $filter = null;
public function __construct(Iterator $iterator, $filter) {
parent::__construct($iterator);
$this->filter = $filter;
}
public function accept() {
$current = $this->getInnerIterator()->current();
if (strpos($current, $this->filter) !== false) {
return true;
}
return false;
}
}
// Usage
$aUsers = [ 'John', 'Carlos', 'Anna', 'Julia' ];
$oFootball = new ArrayIterator(["**John**" ,"**Carlos**" ,"Daniel" ,"Rob" ,"Frank" ,"Bob"]);
foreach ($aUsers as $sUser) {
$oFilter = new NameFilterIterator($oFootball, $sUser);
foreach ($oFilter as $sName) {
var_dump($sName); // outputs: John, Carlos
}
}
The internal memory usage of the FilterIterator object is way more efficient.
Upvotes: 1