:)
提前感谢您帮我解决这个问题:
我有一个实体酒店,它与实体HotelService
有ManyToMany关系我如何构建(如果可能的话,使用QueryBuilder)一个查询来选择所有具有作为数组参数给出的服务子集的酒店?
示例:H1(S1,S2,S3,S4),H2(S2,S3,S4),H3(S1,S2,S3)
使用子集(S1,S2)查询必须返回H1和H3。
我尝试了很多东西,这是一些代码提取:
public function findByServices($services) {
$qb = $this->createQueryBuilder('hotel')
->addSelect('location')
->addSelect('country')
->addSelect('billing')
->addSelect('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))->getQuery();
}
此代码返回$ arrayIds中有一个服务ID的所有酒店。
我想要相反的(在$ arrayIds中服务包含所有ID的酒店)。
当然,在expr() - >中反转参数并不能解决问题,并且会产生错误的参数错误。
是的,有人能帮帮我吗? (抱歉我的英语不好):)答案 0 :(得分:1)
对于您的解决方案,您可以将COUNT(DISTINCT)
与HAVING
和GROUP BY
条款一起使用
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();
}
在上面的查询中,我添加了一个select作为计算每个酒店的不同服务ID,即
- > addSelect(' COUNT(DISTINCT services.id)作为HIDDEN total_services')
然后我还需要一个小组,因为我添加了
- > addGroupBy(' hotel.id&#39)
现在这里有一个棘手的部分,因为你提到你需要拥有所有服务ID的酒店,如ids(1,2,3)所以当我们在其执行或操作中使用时,应该返回包含这3个服务的酒店where servid_id = 1 or servid_id = 2 servid_id = 3
这正是你不希望酒店必须拥有这些3的AND
操作所以我通过部分转换了这个逻辑
- >有(' total_services =' .count($ arrayIds))
现在total_services
是查询的虚拟别名,并保留每个酒店的非重复计数,因此我将此计数与IN()
部分中提供的ID的计数进行比较,这将返回必须的酒店包含这些服务
GROUP BY and HAVING Clause