1

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

open-ecommerce.org
  • 1,763
  • 1
  • 25
  • 41
  • Possible duplicate of [MySQL search in comma list](https://stackoverflow.com/questions/5458703/mysql-search-in-comma-list) – SiZE Jun 15 '17 at 17:13

0 Answers0