学说2:如何使用子查询列(在SELECT子句中)

时间:2013-08-10 14:26:47

标签: doctrine-orm

我正在尝试使用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 个答案:

答案 0 :(得分:20)

$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);

答案 1 :(得分:11)

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

$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 ...

答案 2 :(得分:1)

在我的场景中,我需要查看一个联接并找到一个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
        
}

答案 3 :(得分:0)

我知道这是一个老问题,但是如果您愿意,可以使用其他查询构建器作为子查询:

 $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);