Doctrine Query builder,计算相关的一对多行

Posted

技术标签:

【中文标题】Doctrine Query builder,计算相关的一对多行【英文标题】:Doctrine Query builder, count related one to many rows 【发布时间】:2015-04-09 04:43:07 【问题描述】:
<?php
namespace Raltech\WarehouseBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity
 * @ORM\Table(name="warehouse_magazine")
 */
class Magazine

    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=100)
     */
    protected $name;


    /**
     * @ORM\Column(type="text")
     */
    protected $description;


    /**
     * @ORM\OneToMany(targetEntity="Wardrobe", mappedBy="magazine",cascade="remove")
    */
    protected $wardrobe;


    public function __construct()
    
        $this->wardrobe = new ArrayCollection();
    

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    
        return $this->id;
    

    /**
     * Set name
     *
     * @param string $name
     * @return Magazine
     */
    public function setName($name)
    
        $this->name = $name;

        return $this;
    

    /**
     * Get name
     *
     * @return string 
     */
    public function getName()
    
        return $this->name;
    

    /**
     * Set description
     *
     * @param string $description
     * @return Magazine
     */
    public function setDescription($description)
    
        $this->description = $description;

        return $this;
    

    /**
     * Get description
     *
     * @return string 
     */
    public function getDescription()
    
        return $this->description;
    

    /**
     * Add wardrobe
     *
     * @param \Raltech\WarehouseBundle\Entity\Wardrobe $wardrobe
     * @return Magazine
     */
    public function addWardrobe(\Raltech\WarehouseBundle\Entity\Wardrobe $wardrobe)
    
        $this->wardrobe[] = $wardrobe;

        return $this;
    

    /**
     * Remove wardrobe
     *
     * @param \Raltech\WarehouseBundle\Entity\Wardrobe $wardrobe
     */
    public function removeWardrobe(\Raltech\WarehouseBundle\Entity\Wardrobe $wardrobe)
    
        $this->wardrobe->removeElement($wardrobe);
    

    /**
     * Get wardrobe
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getWardrobe()
    
        return $this->wardrobe;
    



<?php
namespace Raltech\WarehouseBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="warehouse_wardrobe")
 */
class Wardrobe

    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=100)
     */
    protected $name;


    /**
     * @ORM\Column(type="text")
     */
    protected $description;


    /**
     * @ORM\ManyToOne(targetEntity="Magazine", inversedBy="wardrobe")
     * @ORM\JoinColumn(name="magazine_id", referencedColumnName="id")
     */
    protected $magazine;

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    
        return $this->id;
    

    /**
     * Set name
     *
     * @param string $name
     * @return Wardrobe
     */
    public function setName($name)
    
        $this->name = $name;

        return $this;
    

    /**
     * Get name
     *
     * @return string 
     */
    public function getName()
    
        return $this->name;
    

    /**
     * Set description
     *
     * @param string $description
     * @return Wardrobe
     */
    public function setDescription($description)
    
        $this->description = $description;

        return $this;
    

    /**
     * Get description
     *
     * @return string 
     */
    public function getDescription()
    
        return $this->description;
    

    /**
     * Set magazine
     *
     * @param \Raltech\WarehouseBundle\Entity\Magazine $magazine
     * @return Wardrobe
     */
    public function setMagazine(\Raltech\WarehouseBundle\Entity\Magazine $magazine = null)
    
        $this->magazine = $magazine;

        return $this;
    

    /**
     * Get magazine
     *
     * @return \Raltech\WarehouseBundle\Entity\Magazine 
     */
    public function getMagazine()
    
        return $this->magazine;
    

我的 2 个实体,我想计算每个杂志有多少衣橱相关,我必须从 querybuilder 做这个

$em = $this->get('doctrine.orm.entity_manager');
$userRepository = $em->getRepository('Raltech\WarehouseBundle\Entity\Magazine');
$qb = $userRepository->createQueryBuilder('magazine')
    ->addSelect("magazine.id,magazine.name,magazine.description")
    ->InnerJoin('magazine.wardrobe', 'wardrobe')
    ->addSelect('COUNT(wardrobe.id) AS wardrobecount')

这当然行不通。 那么,有人可以提供示例如何从查询构建器中计算这个吗?

【问题讨论】:

添加-&gt;groupBy('magazine.id') ? 我觉得应该是innerJoin,小写的“i”。 它有效,但我怎么能显示不相关(wardrobecount == 0)? leftJoin代替innerJoin 【参考方案1】:

总结cmets:

$qb = $userRepository->createQueryBuilder('magazine')
->addSelect("magazine.id,magazine.name,magazine.description")
->leftJoin('magazine.wardrobe', 'wardrobe') // To show as well the magazines without wardrobes related
->addSelect('COUNT(wardrobe.id) AS wardrobecount')
->groupBy('magazine.id'); // To group the results per magazine

【讨论】:

当我想计算两个不同的关系时会发生什么,例如衣柜数和洗漱用品数? 您应该能够再次进行左连接-&gt;leftJoin('magazine.toletries', 'toiletries'),然后在另一列-&gt;addSelect('COUNT(toletries.id) AS toiletriescount') 上选择计数。不过,您可能想做-&gt;addSelect('COUNT(distinct toletries.id) AS toiletriescount'),这取决于您的需要,因为它是左连接。 我比较关心group by。我想我的例子并不能说明这个问题。假设您正在计算与杂志以外的事物相关的内容。我基本上会建议使用子查询。分组依据不够灵活。在这种特殊情况下效果很好,但无法扩展。

以上是关于Doctrine Query builder,计算相关的一对多行的主要内容,如果未能解决你的问题,请参考以下文章

Doctrine Query Builder 使用数组

Doctrine Query Builder,“介于”表达式和子查询之间

Doctrine Query Builder,“between”表达式和子查询

Doctrine DBAL 可以与 ORM Query Builder 混合使用吗?

Doctrine2 查询(Builder)在使用“where”和“in”子句后失去关系

Symfony Query Builder join ON 和 WITH 区别