Doctrine 2查询构建器和leftJoin子查询

时间:2014-03-26 21:29:20

标签: doctrine-orm

我有以下实体。

实体产品:

namespace App\Model;

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

/**
 * @ORM\Entity
 */
class Product extends Object
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue
     * @var int
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="Category")
     * @ORM\JoinColumn(name="category_id", referencedColumnName="id", onDelete="SET NULL")
     * @var int
     */
    private $category;

    /**
     * @ORM\OneToOne(targetEntity="Image", cascade={"persist", "remove"})
     * @var Image
     */
    private $image;

    /**
     * @ORM\OneToOne(targetEntity="Image", cascade={"persist", "remove"})
     * @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
     * @var Image
     */
    private $backgroundImage;

    /**
     * @ORM\ManyToOne(targetEntity="Layer")
     * @ORM\JoinColumn(name="methodOfPreparing_id", referencedColumnName="id", onDelete="SET NULL")
     * @var Layer|NULL
     */
    private $methodOfPreparing;
}

实体层:

/**
 * @ORM\Entity
 */
class Layer extends Object
{    
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue
     * @var int
     */
    private $id;

    /**
     * @ORM\OneToMany(targetEntity="State", mappedBy="layer", indexBy="position", cascade={"persist", "remove"})
     * @var ArrayCollection
     */
    private $states;

    /**
     * @ORM\Column(type="string")
     * @var string
     */
    private $name;

    /**
     * @ORM\Column(type="integer")
     * @var int
     */
    private $position;
}

实体状态:

/**
 * @ORM\Entity
 */
class State extends Object
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue
     * @var int
     */
    private $id;

    /**
     * @ORM\Column(type="string")
     * @var string
     */
    private $name;

    /**
     * @ORM\ManyToOne(targetEntity="Layer", inversedBy="states")
     * @ORM\JoinColumn(name="layer_id", referencedColumnName="id", onDelete="CASCADE")
     * @var Layer
     */
    private $layer;

    /**
     * @ORM\Column(type="integer")
     * @var int
     */
    private $position;

    /**
     * @ORM\Column(type="integer", columnDefinition="int(1) NOT NULL")
     * @var bool
     */
    private $active;
}

骨架查询:

SELECT Product
    FROM product
        LEFT JOIN 
            (SELECT Layer, State
                FROM layer
                INNER JOIN state ON layer.id = state.layer_id
                WHERE state.active = 1
            ) sub
        ON sub.id = product.methodOfPreparing_id

我需要使用查询构建器创建DQL查询。 有可能是左连接子查询吗?

2 个答案:

答案 0 :(得分:4)

从我发现到目前为止,您无法使用Querybuilder加入子查询。但是你可以按照我的理解使用NativeSQL。

见线程:https://groups.google.com/d/msg/doctrine-user/0rNbXlD0E_8/xMNiQgp9c3QJ

和NativeQueries:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/native-sql.html

答案 1 :(得分:3)

您可以使用WITH子句作为JOIN条件在DQL中执行LEFT JOIN子查询。

如,

SELECT st
FROM SomeThings st
LEFT JOIN st.other ot WITH ot.id = (
  SELECT ot2
  FROM OtherThings ot2
  WHERE ot2.id = 'some ID'
)
WHERE blah blah blah

......或......

SELECT st
FROM SomeThings st
LEFT JOIN st.others ot WITH ot.id IN (
  SELECT ot2
  FROM OtherThings ot2
  WHERE ot2.status = true
)
WHERE blah blah blah

......等等。

以下是我工作的代码库中的工作示例:

SELECT f, df, d
FROM Entities\Main_frames f
LEFT JOIN f.dashboards df WITH df.dashboard IN (
  SELECT dd
  FROM Entities\Main_dashboards dd
  WHERE dd.dashboard_addedby = :createdBy
    AND dd.status = true
)
LEFT JOIN df.dashboard d
INDEX BY f.id
WHERE f.createdBy = :createdBy
  AND f.frame_type IN (2, 6)
  AND f.status = true
ORDER BY f.createdDate

......和......

SELECT m, cm, s
FROM Entities\Main_modules m
LEFT JOIN m.companyModules cm WITH cm.companyid = :companyId
LEFT JOIN m.subscriptions s WITH s.id = (
  SELECT ss
  FROM Entities\Subscriptions ss
  WHERE ss.company = :companyId
    AND ss.module = m.id
    AND ss.createdDate = (
      SELECT MAX(sss.createdDate)
      FROM Entities\Subscriptions sss
      WHERE sss.company = :companyId
        AND sss.module = m.id
  )
)
WHERE m.id <= 4
ORDER BY m.id