【发布时间】:2018-04-14 15:59:49
【问题描述】:
我使用 Doctrine (doctrine/orm v2.6.1) 和 Symfony 创建了两个名为 Project 和 ProjectTag 的实体。我想选择所有标签都带有$tags 中给出的名称的所有项目。我的ProjectRepository.php 中的以下查询在我的开发环境中使用 SQLite:
public function findByAllTags($tags)
{
$queryBuilder = $this->createQueryBuilder('p');
for ($i = 0; $i < count($tags); $i++) {
$tagSubQueryBuilder = $this->createQueryBuilder("p$i")
->join('p.tags', "tags_joined_$i")
->andWhere("tags_joined_$i.name = ?$i");
$queryBuilder->andWhere(
$queryBuilder->expr()->exists($tagSubQueryBuilder->getDQL())
);
}
$queryBuilder->orderBy('p.timeCreated','DESC');
return $queryBuilder->getQuery()->setParameters($tags)->getResult();
}
这被转换为
SELECT
p0_.id AS id_0,
p0_.name AS name_1
FROM
project p0_
WHERE
(
EXISTS (
SELECT
p1_.id
FROM
project p1_
INNER JOIN projects_tags p3_ ON p0_.id = p3_.project_id
INNER JOIN project_tag p2_ ON p2_.id = p3_.project_tag_id
WHERE
p2_.name = ?
)
)
ORDER BY
p0_.created DESC
但是,在我使用 MySQL 的生产环境中,我收到以下错误:
An exception occurred while executing 'SELECT p0_.id AS id_0, p0_.name AS name_1 FROM project p0_ WHERE (EXISTS (SELECT p1_.id FROM project p1_ INNER JOIN projects_tags p3_ ON p0_.id = p3_.project_id INNER JOIN project_tag p2_ ON p2_.id = p3_.project_tag_id WHERE p2_.name = ?)) ORDER BY p0_.created DESC' with params ["video"]:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'p0_.id' in 'on clause'
【问题讨论】:
-
这看起来有点混乱,那个查询应该返回什么?
-
查询应该(和 SQLite 一样)返回项目的项目 ID 和名称(在这种情况下是
id_0和name_1),这些项目的所有标签都带有数组 @987654328 中的名称@。在我发布的自动转换为 SQL 的情况下,$tags仅包含一个元素,因此只有一个EXISTS子句。我使用@ORM/ManyToMany为项目分配标签,反之亦然:@ORM\ManyToMany(targetEntity="App\Entity\ProjectTag", inversedBy="projects") \n @ORM\JoinTable(name="projects_tags")这个连接表是上面的内部连接中使用的 -
您的嵌套查询选择了
project p1_,而没有任何连接条件引用它。为什么不在单个非嵌套查询中内部连接标签表并跳过EXISTS? -
你能举个简短的例子吗?例如,我不确定这将如何让我选择同时具有“视频”和“图片”标签的项目。
标签: symfony doctrine-orm