Is it possible to retrieve all records querying with an array of ids in a field with ids comma separated without query the database for each id?
The field categoriy_id is an integer but the field categories_tree is a varchar with integers separated by comma: "2,5,6"
allowedCats is also an array "5,2"
this is my code
public function getCarouselLatest() {
$userID = Yii::$app->user->identity->id;
$currentUser = UserProfile::find()
->where(['user_id' => $userID])
->one();
$integerIDs = array_map('intval', explode(',', $currentUser->categories_tree));
$latestBooks = Book::find()
->published()
->where(['in', 'category_id', $integerIDs])
->orWhere(new Expression('FIND_IN_SET(:category_to_find, categories_tree)'))
->addParams([':category_to_find' => 2])
->orderBy([
'published_at' => SORT_DESC,
])
->limit(10)
->all();
return $latestBooks;
}
The first where works fine but the challenge is the second where because i need to check a list of numbers into the list of numbers of the catagories_tree field.
I Know now that I can use FIND_IN_SET
->orWhere(new Expression('FIND_IN_SET(:category_to_find, categories_tree)'))
->addParams([':category_to_find' => 2])
That will produce the following sql:
SELECT * FROM `book` WHERE (`category_id` IN (7, 39)) OR (FIND_IN_SET(2, categories_tree)) ORDER BY `published_at` DESC LIMIT 10
But I need to search by a list of ids not only one parameter like in FIND_IN_SET
Probably, for now, I will add multiple where lines using FIND_IN_SET but I guess that will be very heavy for the DB.
I am aware the this is a bad db design and the ids should be in another table and simply do a join, but this involves changing many third party vendors.
Any ideas?
UPDATED
That's the code I am using but not happy because as I said not sure what going to happen with the performance with real data....
public function getCarouselLatest() {
$userID = Yii::$app->user->identity->id;
$currentUser = UserProfile::find()
->where(['user_id' => $userID])
->one();
$integerIDs = array_map('intval', explode(',', $currentUser->categories_tree));
$latestBooks = Book::find()
->published()
->where(['in', 'category_id', $integerIDs]);
foreach ($integerIDs as $cat) {
$latestBooks = $latestBooks->orWhere(new Expression('FIND_IN_SET(:category_to_find'.$cat.', categories_tree)'))
->addParams([':category_to_find'.$cat => $cat]);
}
$latestBooks = $latestBooks->orderBy([
'published_at' => SORT_DESC,
])
->limit(10)
->all();
return $latestBooks;
}
That output:
SELECT * FROM `book` WHERE ((`category_id` IN (7, 39)) OR (FIND_IN_SET(7, categories_tree))) OR (FIND_IN_SET(39, categories_tree)) ORDER BY `published_at` DESC LIMIT 10
in 1.1 ms