Symfony2 - Doctrine2 QueryBuilder WHERE IN ManyToMany field

后端 未结 1 1613
被撕碎了的回忆
被撕碎了的回忆 2020-12-11 11:34

:)

Thank you in advance for helping me with this issue:

I\'ve an entity Hotel which has a ManyToMany relation with an entity HotelService

how can i b

相关标签:
1条回答
  • 2020-12-11 12:30

    For your solution you can make use of COUNT(DISTINCT) with HAVING and GROUP BY clauses

    public function findByServices($services)
    {
        $qb = $this->createQueryBuilder('hotel')
            ->addSelect('location')
            ->addSelect('country')
            ->addSelect('billing')
            ->addSelect('services')
            ->addSelect('COUNT(DISTINCT  services.id) AS total_services')
            ->innerJoin('hotel.billing', 'billing')
            ->innerJoin('hotel.location', 'location')
            ->innerJoin('location.city', 'city')
            ->innerJoin('location.country', 'country')
            ->innerJoin('hotel.services', 'services');
        $i = 0;
        $arrayIds = array();
        foreach ($services as $service) {
            $arrayIds[$i++] = $service->getId();
        }
        $qb->add('where', $qb->expr()->in('services', $arrayIds))
            ->addGroupBy('hotel.id')
            ->having('total_services = '.count($arrayIds))
            ->getQuery();
    }
    

    In above query i have added one more select as counting distinct service ids for each hotel i.e

    ->addSelect('COUNT(DISTINCT services.id) AS HIDDEN total_services')

    Then i also need a group by for that count so i added

    ->addGroupBy('hotel.id')


    Now here comes the tricky part as you mentioned that you need hotel that have all the service ids like ids (1,2,3) so hotels that contains these 3 service should be returned when we use in its performs or operation like where servid_id = 1 or servid_id = 2 servid_id = 3 which is exactly you don't want the AND operation that hotel must have these 3 so i converted this logic by having part

    ->having('total_services = '.count($arrayIds))

    Now total_services is a virtual alias for the query and holds the distinct count for each hotel so i have compared this count to the count of provided ids in IN() part this will return the hotels which must contains these services


    GROUP BY and HAVING Clause

    0 讨论(0)
提交回复
热议问题