如何使用查询构建器基于内部连接关系编写具有不同的自连接查询?
How to write this self joined query with distinct based on the inner join relationship using the query builder?
我有一个实体 Place
可以包含许多不同类型的地方,特别是在这种情况下“城市”和“州”,其中每个“城市”可以包含对相同 table 指向父“状态”。
我有另一个实体 Office
与 Place
存在多对一关系,但由于域限制,办公室只能链接到“城市”,而不会链接到“城市” “状态”。
我必须编写一个查询来获取我们拥有一个或多个办事处的所有州,但仅限于那些州。
在简单的 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 much 更清晰和易于管理。
目前我们使用的是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': Error: Cannot select entity through identification variables without choosing at least one root entity alias
我们怎样才能让这个查询起作用?
感谢和问候。
我认为您发布了一个不完整的基本 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中的inner join。
来源:
如果没有看到实体(至少对我而言),很难找出您应该构建的查询。例如:你有 mappedBy 字段吗?但我认为您的问题是您没有从 PartnerOffice 获取任何信息,而它是您的根条目(来自)。将您的 ->select()
更改为 ->addSelect
但这将为每条记录获取整个 PartnerOffice 实体,并且您的 distinct 可能无法按预期工作,或者使用 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\'');
我有一个实体 Place
可以包含许多不同类型的地方,特别是在这种情况下“城市”和“州”,其中每个“城市”可以包含对相同 table 指向父“状态”。
我有另一个实体 Office
与 Place
存在多对一关系,但由于域限制,办公室只能链接到“城市”,而不会链接到“城市” “状态”。
我必须编写一个查询来获取我们拥有一个或多个办事处的所有州,但仅限于那些州。
在简单的 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 much 更清晰和易于管理。
目前我们使用的是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': Error: Cannot select entity through identification variables without choosing at least one root entity alias
我们怎样才能让这个查询起作用?
感谢和问候。
我认为您发布了一个不完整的基本 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中的inner join。
来源:
如果没有看到实体(至少对我而言),很难找出您应该构建的查询。例如:你有 mappedBy 字段吗?但我认为您的问题是您没有从 PartnerOffice 获取任何信息,而它是您的根条目(来自)。将您的 ->select()
更改为 ->addSelect
但这将为每条记录获取整个 PartnerOffice 实体,并且您的 distinct 可能无法按预期工作,或者使用 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\'');