如何使用查询生成器基于内部联接关系编写具有distinct的自联接查询



我有一个实体Place,它可以容纳许多不同类型的位置,特别是在这种情况下"城市;以及";状态";,其中每个";城市;可以保存指向父"的对同一表的引用;状态";。

我有另一个与Place具有多对一关系的实体Office,但由于域限制,办公室将仅链接到";城市";,永远不要成为";状态";。

我必须写一个查询,以获取我们有一个或多个办公室的所有州,但仅限于这些州。

在普通的SQL中,查询很容易实现:

SELECT DISTINCT states.*
FROM offices o
INNER JOIN places cities ON cities.id = o.place_id
INNER JOIN places states ON cities.parent_place_id = states.id
WHERE p.place_type = 'city'

这是有效的,我们得到了我们所需要的。

但是我需要(我更愿意(使用查询生成器编写查询。这是";基本";查询,但我们需要有条件地再应用几个过滤器,这将使QB的使用更加干净和易于管理。

目前我们使用的是Native Query,但这意味着我们需要在调用em::createNativeQuery()之前操作SQL字符串,这很麻烦。

$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('states')->distinct()
->from(PartnerOffice::class, 'o')
->innerJoin('o.place', 'p')
->innerJoin('p.parentPlace', 'states')
->where("p.placeType = 'city'");

但这给出了一个关于的错误

SELECT DISTINCT’:错误:如果不选择至少一个根实体别名,则无法通过标识变量选择实体

我们如何使此查询工作?

谢谢和问候。

如果没有看到实体(至少对我来说(,很难确定应该构建的查询。你有地图旁的田地吗?但我认为你的问题是,当PartnerOffice是你的根条目时,你没有从中获取任何信息。将您的->select()更改为->addSelect,但这将为每条记录获取整个PartnerOffice实体,而您的不同可能无法按预期工作,或者使用Place实体作为根条目并翻转逻辑。

让我们假设您的实体的关系是双向的。这样的东西应该可以做到(但您可能需要为实际实体和字段名称更改它(。

$this->getEntityManager()->createQueryBuilder()
->distinct()
->from(Place::class, 'p')
->join('p.cities', 'c')
->join(PartnerOffice::class, 'po', Join::WITH, 'po.place = p')
->andWhere('p.placeType = 'state'');

我认为您发布了一个不完整的基本sql查询(WHERE AND(,并创建了一个别名p.place_type,该别名在查询中没有定义。然而,从你的声明来看,我认为你可以尝试下面的查询,

$qb->selectRaw('DISTINCT s.states')
->from('offices as o')
->join('places as c', 'c.id', '=', 'o.place_id')
->join('places as s', 's.id', '=', 'c.parent_place_id')
->where('c.placeType', 'city')->get();

默认情况下,->join()是指queryBuilder中的内部联接。

来源:

  1. https://laravel.com/docs/8.x/queries#inner-联接条款

最新更新