25

我正在尝试使用 SELECT 子句中的子查询进行简单的选择查询,但根本没有找到方法。我已经尝试过使用 DQL 和 QueryBuilder,但都不起作用。代码如下,请不要说我可以只使用连接,这是一个简化的示例,只是为了说明问题,我有子查询的合法用例。

// With QueryBuilder
$query = $qb->select(array('a', 
                           '(SELECT at.addresstypeName 
                               FROM e:Addresstype at 
                              WHERE at.addresstypeId = a.addresstypeId
                            ) AS addresstypeName'))
            ->from('e:Address', 'a')
            ->where('a.addressId = :addressId')
            ->setParameter('addressId', 1);

// With DQL
$dql = "SELECT a, 
               (SELECT at.addresstypeName 
                  FROM e:Addresstype at 
                 WHERE at.addresstypeId = a.addresstypeId
               ) AS addresstypeName 
          FROM e:Address a 
         WHERE a.addressId = :addressId";
$query = $em->createQuery($dql)->setParameter(':addressId', 1);

地址表中定义了以下关系:

/**
 * @ORM\ManyToOne(targetEntity="Addresstype")
 * @ORM\JoinColumns({
 *   @ORM\JoinColumn(name="addresstype_id", referencedColumnName="addresstype_id")
 * })
 */
protected $addresstype;

在本机 SQL 中,查询如下所示:

SELECT
    a.*,
    (
        SELECT at.addresstype_name
        FROM addresstype at
        WHERE at.addresstype_id = a.addresstype_id
    ) AS addresstype_name
FROM address a
WHERE a.address_id = 1

有任何想法吗?

4

4 回答 4

29
$query = $qb->select('a')
    ->addSelect('(SELECT at.addresstypeName
            FROM e:Addresstype at
            WHERE at.addresstypeId = a.addresstypeId) AS addresstypeName'
        )
    ->from('e:Address', 'a')
    ->where('a.addressId = :addressId')
    ->setParameter('addressId', 1);
于 2013-08-10T17:30:42.513 回答
15

对我来说,带有教义的子查询适用于此查询:

$qb->select('e.field')
   ->addSelect('(SELECT count(mv.nm)
                FROM Clt\Bundle\MyBundle\Entity\MV mv
                LEFT JOIN Clt\Bundle\MyBundle\Entity\M ma WITH  mv.nm=ma.nm
                WHERE mv.ne=e.ne and ma.nm is null
                ) AS nm'
   )
   ->from($this->_entityName, 'e')
   ->leftJoin('e.m', 'm')
   ->where($qb->expr()->eq('t.id'.$typeModule, $idElementModule));

请注意,在左连接中,您必须使用 WITH 而不是 ON...

于 2014-04-09T14:22:10.053 回答
6

我知道这是一个老问题,但如果你愿意,你可以使用另一个查询生成器作为你的子查询:

 $qb->select("a")
            ->addSelect("(" . $qb2->select("at.addresstypeName")
                ->from("e:Addresstype", "at")
                ->where("at.addresstypeId = a.addresstypeId")
                ->getDQL() . ") AS addresstypeName"
            )
            ->from('e:Address', 'a')
            ->where('a.addressId = :addressId')
            ->setParameter('addressId', 1);
于 2019-10-26T00:19:18.177 回答
2

在我的场景中,我需要查看一个连接并找到一个 Id 并将其用作布尔值,找到 1 否则为 0,然后将其应用于 orderBy。DQL 表达式仅在与 Where 子句结合使用时才有效,这不是我的情况。所以,一个 DQL 子选择救了我。

或多或少地适应了您的场景,它看起来像这样:

// With QueryBuilder
// In AddressRepository
// Where one address may belong to several addressTypes

public function getWithType($addressType){

$qb = $this->createQueryBuilder('a1');
$qb->addSelect('a1.someField', 'a1.otherField')
$qb->addSelect(
        '(SELECT at.addressTypeName 
        FROM App\Entity\Address a2
        JOIN a2.addressType at
        WHERE at.id = '.$addressType.' AND a2.id = a1.id
        ) AS addressTypeName')
//The rest part of the query
        
}
于 2020-09-28T08:49:55.323 回答