我有一个名为Company
的实体。关联映射如下:
manyToOne:
headCompany:
targetEntity: CompanyEntity
inversedBy: headCompany
oneToMany:
subsidiaries:
targetEntity: CompanyEntity
mappedBy: headCompany
一切正常。公司可以是另一家公司的子公司和/或拥有自己的子公司。
现在,我需要过滤其他公司或拥有子公司的公司。
我可以直接用SQL做到这一点:
SELECT c.id, COUNT(s.headCompany_id) subsidiaries FROM companies c LEFT JOIN companies s ON s.headCompany_id = c.id GROUP BY c.id HAVING subsidiaries > 0
导致这样的事情:
+----+--------------+
| id | subsidiaries |
+----+--------------+
| 1 | 3 |
+----+--------------+
| 5 | 2 |
+----+--------------+
然后,公司1和5适合我的过滤器,因为他们都有子公司。
如何使用Doctrine Query Builder实现相同的结果?
我的尝试是:
$query = $qb->select('e')
->from('CompanyEntity', 'e')
->orderBy('e.id', 'ASC')
->join('e.headCompany', 'h')
->addSelect("COUNT(h.id) as subsidiaries")
->groupBy("e.id")
->having("subsidiaries > 0");
这个回归子公司,而非主要公司。
->where($qb->expr()->isNotNull("e.subsidiaries"))
显然,Doctrine不允许这样做。
答案 0 :(得分:0)
如何反转加入条款,选择公司并加入子公司,然后对与每家公司相关的子公司数量应用过滤器
$query = $qb->select('h,s')
->from('CompanyEntity', 'h')
->join('h.subsidiaries', 's')
->addSelect("COUNT(s.id) AS HIDDEN subsidiaries")
->groupBy("h.id")
->orderBy('h.id', 'ASC')
->having("subsidiaries > 0");
当您使用sqlmode =>only_full_group_by时,除非它们存在于分组依据中,否则您无法选择实体的所有列,因此必须在
select()
中选择要返回的列。
$query = $qb->select('h.id')
->from('CompanyEntity', 'h')
->join('h.subsidiaries', 's')
->addSelect("COUNT(s.id) AS HIDDEN subsidiaries")
->groupBy("h.id")
->orderBy('h.id', 'ASC')
->having("subsidiaries > 0");
根据官方文档“ONLY_FULL_GROUP_BY拒绝查询,其中选择列表,HAVING条件或ORDER BY列表引用既未在GROUP BY子句中命名也未在功能上依赖于(唯一确定)GROUP BY列的非聚合列。“
答案 1 :(得分:0)
您应该能够逐个使用订单,有点像这样:
$query = $qb->select('e')
->from('CompanyEntity', 'e')
->join('e.headCompany', 'h')
->addSelect("(CASE WHEN COUNT(h.id) > 0 THEN 1 ELSE 0 END) as sort_sub")
->groupBy("e.id")
->orderBy("sort_sub");
您可以在此主题中详细了解它:How to ORDER BY CASE in Doctrine2 (Symfony2)