Php 原则DQL-WHERE子句中的嵌套子查询抛出语法错误

Php 原则DQL-WHERE子句中的嵌套子查询抛出语法错误,php,sql-server,symfony,doctrine,Php,Sql Server,Symfony,Doctrine,我试图根据两个关联表的汇总和合并结果从一个表中查询数据。 当作为本机SQL执行时,查询工作正常,不幸的是,我的应用程序仅限于在QueryBuilder对象上使用Doctrine的DQL 以下是我构建QueryBuilder的方式: $resUnitQuery=$queryBuilder->getEntityManager->createQueryBuilder; $resUnitQuery->选择“COALESCESUMpc.residentialUnits,0” ->fromPropertyC

我试图根据两个关联表的汇总和合并结果从一个表中查询数据。 当作为本机SQL执行时,查询工作正常,不幸的是,我的应用程序仅限于在QueryBuilder对象上使用Doctrine的DQL

以下是我构建QueryBuilder的方式:

$resUnitQuery=$queryBuilder->getEntityManager->createQueryBuilder; $resUnitQuery->选择“COALESCESUMpc.residentialUnits,0” ->fromPropertyConnection::类“pc” ->其中$rootAlias.id=pc.contract; $comUnitQuery=$queryBuilder->getEntityManager->createQueryBuilder; $comUnitQuery->选择“COALESCESUMpwa.residential\u units,0” ->fromPropertyWithoutAddress::类“pwa” ->其中$rootAlias.id=pwa.contract; $queryBuilder=$this->getEntityManagerContract::class->createQueryBuilder; $queryBuilder ->选择“id” ->fromContract::类“o” ->在哪里
“:residentialUnits正确,DBAL不支持对子查询进行算术运算。另外,DBAL不支持联接子查询,请从中联接选择。。。在不使用本机查询的情况下打开

另一个问题是子查询的WHERE语句依赖于根查询,将导致根查询执行完整表扫描。每行执行每个子查询,除非向根查询添加了条件,其中o.id

由于子查询和值取决于根查询id。您可以重写查询,将子查询用作隐藏列和HAVING子句,从添加的列结果中筛选id结果集

$em = $queryBuilder->getEntityManager();
$expr = $em->getExpressionBuilder();

$qbPC = $em->createQueryBuilder()
    ->select('COALESCE(SUM(pc.residentialUnits), 0)')
    ->from(App\Entity\PropertyConnection::class, 'pc')
    ->where($expr->eq('pc.contract', "$rootAlias.id"));

$qbPWA = $em->createQueryBuilder()
    ->select('COALESCE(SUM(pwa.residential_units), 0)')
    ->from(App\Entity\PropertyWithoutAddress::class, 'pwa')
    ->where($expr->eq('pwa.contract', "$rootAlias.id"));

$qb = $this->getEntityManager(Contract::class)
    ->createQueryBuilder()
    ->select('o.id')
    ->from(App\Entity\Contract::class, 'o')
    ->addSelect('(' . $qbPC->getDQL() . ') AS HIDDEN pc_ru')
    ->addSelect('(' . $qbPWA->getDQL() . ') AS HIDDEN pwa_ru')
    ->having($expr->lte(':v', 'pc_ru + pwa_ru'))
    ->setParameter('v', $params['rangeFrom']);

dump($qb->getDQL());
结果DQL

SELECT 
    o.id, 
    (SELECT 
         COALESCE(SUM(pc.residentialUnits), 0) 
     FROM App\Entity\PropertyConnection pc 
     WHERE pc.contract = o.id
    ) AS HIDDEN pc_ru, 
    (SELECT 
         COALESCE(SUM(pwa.residential_units), 0) 
     FROM App\Entity\PropertyWithoutAddress pwa 
     WHERE pwa.contract = o.id
    ) AS HIDDEN pwa_ru 
FROM App\Entity\Contract o 
HAVING :v <= pc_ru + pwa_ru

正确,DBAL不支持对子查询进行算术运算。另外,DBAL不支持联接子查询,请从中联接选择。。。在不使用本机查询的情况下打开

另一个问题是子查询的WHERE语句依赖于根查询,将导致根查询执行完整表扫描。每行执行每个子查询,除非向根查询添加了条件,其中o.id

由于子查询和值取决于根查询id。您可以重写查询,将子查询用作隐藏列和HAVING子句,从添加的列结果中筛选id结果集

$em = $queryBuilder->getEntityManager();
$expr = $em->getExpressionBuilder();

$qbPC = $em->createQueryBuilder()
    ->select('COALESCE(SUM(pc.residentialUnits), 0)')
    ->from(App\Entity\PropertyConnection::class, 'pc')
    ->where($expr->eq('pc.contract', "$rootAlias.id"));

$qbPWA = $em->createQueryBuilder()
    ->select('COALESCE(SUM(pwa.residential_units), 0)')
    ->from(App\Entity\PropertyWithoutAddress::class, 'pwa')
    ->where($expr->eq('pwa.contract', "$rootAlias.id"));

$qb = $this->getEntityManager(Contract::class)
    ->createQueryBuilder()
    ->select('o.id')
    ->from(App\Entity\Contract::class, 'o')
    ->addSelect('(' . $qbPC->getDQL() . ') AS HIDDEN pc_ru')
    ->addSelect('(' . $qbPWA->getDQL() . ') AS HIDDEN pwa_ru')
    ->having($expr->lte(':v', 'pc_ru + pwa_ru'))
    ->setParameter('v', $params['rangeFrom']);

dump($qb->getDQL());
结果DQL

SELECT 
    o.id, 
    (SELECT 
         COALESCE(SUM(pc.residentialUnits), 0) 
     FROM App\Entity\PropertyConnection pc 
     WHERE pc.contract = o.id
    ) AS HIDDEN pc_ru, 
    (SELECT 
         COALESCE(SUM(pwa.residential_units), 0) 
     FROM App\Entity\PropertyWithoutAddress pwa 
     WHERE pwa.contract = o.id
    ) AS HIDDEN pwa_ru 
FROM App\Entity\Contract o 
HAVING :v <= pc_ru + pwa_ru

谢谢你的快速回复。Doctrine现在似乎能够解析它,不幸的是,我的数据库不知道我们在子查询中定义的两个隐藏别名:SQL错误[207][S0001]:无效列名“sclr_46”。sclr_46是作为第一个子查询的别名生成的变量。如果有帮助的话,我使用的是SQLServer。@Renetharsis不幸的是,MSSQL不像其他RDBMS那样在HAVING子句中支持聚合列别名,而且ORM还没有构建来解析复杂的查询。要解决此问题,您需要在发出合同查询之前使用本机查询或过滤ID。有关此问题的详细信息,请参见:这很遗憾。那我就得解决这个问题了。非常感谢你的支持。由于您的答复对其他DBMS有效,我将其标记为已解决!谢谢你的快速回复。Doctrine现在似乎能够解析它,不幸的是,我的数据库不知道我们在子查询中定义的两个隐藏别名:SQL错误[207][S0001]:无效列名“sclr_46”。sclr_46是作为第一个子查询的别名生成的变量。如果有帮助的话,我使用的是SQLServer。@Renetharsis不幸的是,MSSQL不像其他RDBMS那样在HAVING子句中支持聚合列别名,而且ORM还没有构建来解析复杂的查询。要解决此问题,您需要在发出合同查询之前使用本机查询或过滤ID。有关此问题的详细信息,请参见:这很遗憾。那我就得解决这个问题了。非常感谢你的支持。由于您的答复对其他DBMS有效,我将其标记为已解决!