【问题标题】:Symfony3/Doctrine2 : subquery with InnerJoin using QueryBuilderSymfony3/Doctrine2:使用 QueryBuilder 的 InnerJoin 子查询
【发布时间】:2017-07-13 18:33:55
【问题描述】:

在目录中,我有产品和文章。文章是产品的变体。 在目录中,产品按类别排序,一个产品可以在目录中出现一次或多次。

我想获取目录中的文章,但我的文章没有直接分配到目录,只有产品。

我想使用 Doctrine 的查询构建器构建以下 SQL:

SELECT a.code, a.productCode, a.name
FROM Article a
INNER JOIN (
    SELECT p.code
    FROM Product p
    WHERE p.catalogCode = 'MYCODE'
    GROUP BY p.code
    ORDER BY p.code ASC
) AS results ON results.productCode = a.productCode

此查询在 MySQL 中有效。我尝试在我的实体的存储库中执行此操作,但出现错误:

public function findArticlesByCatalog($catatlogCode)
{
   return $this->getEntityManager()
        ->createQuery(
            'SELECT a.code, a.productCode, a.name
                FROM AppBundle:Article a
                INNER JOIN (
                    SELECT p.code
                    FROM AppBundle:CatalogProduct p
                    WHERE p.catalogCode = :code
                    GROUP BY p.code
                    ORDER BY p.code ASC
                ) AS results ON results.productCode = a.productCode'
        )
        ->setParameter('code', $catatlogCode)
        ->getResult();
}

错误(就在 INNER JOIN 之后):

[Semantical Error] line 0, col 81 near '(
SELECT': Error: Class '(' is not defined.

所以,我想在我的 Controller 中使用 Doctrine 的查询构建器来构建它。

我开始了一些事情,但我不知道要完成它......

$repository = $em->getRepository('AppBundle:Article');

$qb = $repository->createQueryBuilder('a');
$qb->select(array('a.code', 'a.productCode', 'a.name'))
    ->innerJoin(
        'AppBundle:CatalogProduct', 'p',
        'WITH',
        $qb->select('p.code')
           ->where(
              $qb->expr()->eq('p.catalogCode', ':code')
           )
           ->setParameter('code', $catCode)
           ->groupBy('p.code')
           ->orderBy('p.code', 'ASC')
    )
// ...

如何指定查询的其余部分?

AS results ON results.productCode = a.productCode'

感谢您的帮助!

【问题讨论】:

  • @LBA 谢谢,但与我的查询相比,我不太了解。我应该使用 CatalogProduct 存储库创建第二个查询构建器并获取它的 DQL 吗?我已经更新了我的帖子。我对ASON 的部分查询有疑问...你能给我写点什么吗?

标签: mysql doctrine-orm symfony query-builder dql


【解决方案1】:

我找到了正确的方法。

我重写了我的 SQL 以与我的第一个 SQL 相同,以便使用查询生成器轻松完成。

所以,我的第一个 SQL :

SELECT a.code, a.productCode, a.name
FROM Article a
INNER JOIN (
    SELECT p.code
    FROM Product p
    WHERE p.catalogCode = 'MYCODE'
    GROUP BY p.code
    ORDER BY p.code ASC
) AS cat_art ON cat_art.productCode = a.productCode

...与这个结果相同:

SELECT DISTINCT a.code, a.productCode, a.name
FROM Article a
JOIN Product p ON a.productCode = p.code
WHERE p.code IN (
    SELECT p.code
    FROM Product p
    WHERE p.catalogCode = 'MYCODE'
    GROUP BY p.code
    ORDER BY p.code ASC
)

使用查询构建器,我们应该使用 2 个不同的查询构建器编写 2 个查询:

# It is very important here to name it "p2", not "p" because,
# in the main query, there is already "p"
$qb2 = $em->getRepository('AppBundle:CatalogProduct')->createQueryBuilder('p2');

$subQuery = $qb2->select('p2.code')
    ->where(
        $qb2->expr()->eq('p2.catalogCode', ':code')
    )
    ->groupBy('p2.code')
    ->orderBy('p2.code', 'ASC');

# main query
$qb = $em->getRepository('AppBundle:Article')->createQueryBuilder('a');

$query = $qb->select(array('DISTINCT a.code', 'a.productCode', 'a.name', 'p.code AS productCode'))
    ->join('AppBundle:CatalogProduct', 'p', 'WITH', 'a.productCode = p.code')
    ->where(
        $qb->expr()->in(
            'p.code',
            $subQuery->getDQL()
        )
    )
    // Parameter used in subquery must be set in main query.
    ->setParameter('code', $catCode)
    ->getQuery();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多