MySQL — PHP-код для поиска нескольких слов в VARCHAR

Из моего приложения я отправляю список пользователей, которым я хочу найти группу, на которую они подписаны:

$selectedUsers = ["John", "Carlos", "Anna", "Julia"]

У меня в базе данных много разных групп с множеством разных пользователей в
каждый из них:

$football = ["**John**" ,"**Carlos**" ,"Daniel" ,"Rob" ,"Frank" ,"Bob"]

$cooking = ["**John**" , "**Anna**" , "**Julia**" , "Claudia" , "Rob" , "Adriana"]

$startups = ["**John**", "**Carlos**", "**Anna**", "**Julia**", "Rob", "Adriana"]

Вывод, который я хочу получить, это отсортированный список групп с количеством selectedUsers:

$returnArray[0] = $startups //4 users inside group
$returnArray[1] = $cooking //3 users inside group
$returnArray[2] = $football //2 users inside group

Вот код, который у меня есть, но цикл, который я использую, основан на сохраненном мной group_id, и я хочу это изменить:

<?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);
?>

Есть ли какой-нибудь другой способ улучшить / найти более эффективный способ поиска в моей базе данных? Оценил!

1

Решение

Похоже, ваша база данных не нормализована. Нормализованная база данных может быть более эффективным способом. Не храните пользователей в описывающем varchar. Вместо этого установите отношение многих ко многим.

Кроме того, класс FilterIterator в PHP — это то, что вам нужно. Это многоразово и немного более эффективно при переборе массивов.

Вот короткий пример.

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
}
}

Использование внутренней памяти объекта FilterIterator более эффективно.

1

Другие решения

Вы, кажется, смешиваете php и mysql, и было бы лучше изменить дизайн вашей базы данных.

Однако в качестве основной идеи вы можете делать примерно то, что вы хотите в MySQL. Это не красиво и не эффективно, но примерно так:

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
1

По вопросам рекламы [email protected]