2016-07-26 57 views
2

我有問題,試圖重新以下查詢:無法重新創建SQL查詢與學說

select * 
from acme_opties_relaties as r 
inner join acme_options as o on o.id = r.id_a 
inner join acme_option_subgroup as osg on osg.option_id = o.id 
where osg.subgroup_id in (309, 303, 306, 300) 
and o.id <> 47086 
and r.soort = 2 
and o.project_id = 140018 

我所得到的是下面的查詢:

SELECT t0_.id_a AS id_a_17, t0_.id_b AS id_b_18, 
t0_.soort AS soort_0, t1_.id AS id_1, t1_.external_id AS external_id_2, t1_.external_ref AS external_ref_3, t1_.`name` 
AS name_4, t1_.name_sales AS name_sales_5, t1_.price AS price_6, t1_.warranty AS warranty_7, t1_.material AS material_8, t1_.no_option 
AS no_option_9, t1_.print AS print_10, t1_.text_warranty AS text_warranty_11, t1_.text_technical AS text_technical_12, t1_.text_sales AS text_sales_13, t1_.`group` 
AS group_14, t1_.created AS created_15, t1_.updated AS updated_16, t1_.project_id AS project_id_19 
FROM acme_opties_relaties t0_ 
INNER JOIN acme_options t1_ ON 
(t1_.id <> 47086 AND t0_.soort = 2 AND EXISTS 
(SELECT 1 FROM acme_option_subgroup t2_ INNER JOIN acme_subgroep t3_ ON t2_.subgroup_id = t3_.id WHERE t2_.option_id = t1_.id AND t3_.id IN (309, 303, 306, 300)) 
AND t1_.project_id = 140018) 

任何指針/方向,將不勝感激。

<?php 
declare(strict_types = 1); 

namespace Acme\Domain\Entity\Option; 


use Doctrine\ORM\EntityRepository; 
use Doctrine\ORM\Query; 
use Doctrine\ORM\QueryBuilder; 
use Acme\Domain\Entity\Element\SubElement; 
use Acme\Domain\Value\Option\Relation\Type; 

/** 
* Class RelationRepository 
* Relations are interpreted as following. 
* id_a is depending on id_b 
* id_a is selected by id_b 
* id_a is excluded by id_b 
* 
* @package Acme\Domain\Entity\Option 
*/ 
class RelationRepository extends EntityRepository 
{ 
    /** 
    * @var array 
    */ 
    private $directions = ['left', 'right']; 

    /** 
    * getLeft returns the left side of the relations. 
    * 
    * @param Option $option 
    * @param SubElement $subElement 
    * @param Type $type 
    * @return array 
    */ 
    private function getLeft(Option $option, SubElement $subElement, Type $type, bool $inversed = false): Query 
    { 
     return $this->getQuery($option, $subElement, $type, 'left', $inversed); 
    } 

    /** 
    * getRight returns the right side of the relations. 
    * 
    * @param Option $option 
    * @param SubElement $subElement 
    * @param Type $type 
    * @return array 
    */ 
    private function getRight(Option $option, SubElement $subElement, Type $type, bool $inversed = false): Query 
    { 
     return $this->getQuery($option, $subElement, $type, 'right', $inversed); 
    } 

    /** 
    * getQuery returns the full Query needed to get a Collection of Relations. 
    * 
    * @param Option $option 
    * @param SubElement $subElement 
    * @param Type $type 
    * @param string $direction 
    * @return Query 
    */ 
    private function getQuery(Option $option, SubElement $subElement, Type $type, string $direction, bool $inversed): Query 
    { 
     $direction = strtolower($direction); 

     $this->validateDirection($direction); 

     $qb = $this->_em->createQueryBuilder() 
      ->select(['r', 'option']) 
      ->from('Acme\Domain\Entity\Option\Relation', 'r') 
      ->join('Acme\Domain\Entity\Option\Option', 'option') 
     ; 

     $subGroups = iterator_to_array($subElement->getElement()->getSubGroups()); 

     return $this->addDirectionWhere($qb, $direction, $inversed) 
      ->andWhere('r.type=:type') 
      ->andWhere(':subGroup MEMBER OF option.subGroups') 
      ->andWhere('option.project=:project') 
      ->setParameter(':type', $type->getValue()) 
      ->setParameter(':opt', $option->getId()) 
      ->setParameter(':project', $option->getProject()) 
      ->setParameter(':subGroup', $subGroups) 
      ->getQuery(); 
    } 

    /** 
    * validateDirection checks if the direction given is valid. 
    * 
    * @param string $direction 
    */ 
    private function validateDirection(string $direction) 
    { 
     if (!in_array($direction, $this->directions, true)) { 
      throw new \InvalidArgumentException(sprintf('Unexpected direction given [%s]. Expected on of: [%s]', 
       $direction, 
       implode(', ', $direction) 
      )); 
     } 
    } 

    /** 
    * addDirectionWhere returns a prepared QueryBuilder with a WHERE on the side needed. 
    * 
    * @param $direction 
    * @return \Doctrine\ORM\QueryBuilder 
    */ 
    private function addDirectionWhere(QueryBuilder $qb, $direction, $inversed = false): QueryBuilder 
    { 
     switch ($direction) { 
      case 'right': 
       $where = $inversed ? 'r.relation<>:opt' : 'r.relation=:opt'; 
       break; 
      default: 
       $where = $inversed ? 'r.option<>:opt' : 'r.option=:opt'; 
       break; 
     } 

     $qb->where($where); 

     return $qb; 
    } 

    /** 
    * getRequiredOptions returns a Collection of Relations which are required by the given Option. 
    * 
    * @param Option $option 
    * @param SubElement $subElement 
    * @return array 
    */ 
    public function getRequiredOptions(Option $option, SubElement $subElement): array 
    { 
     return $this->getRight($option, $subElement, Type::get(Type::DEPEND))->getResult(); 
    } 

    /** 
    * getDependingOptions returns a Collection of Relations which depend on the given Option. 
    * 
    * @param Option $option 
    * @param SubElement $subElement 
    * @return mixed 
    */ 
    public function getDependingOptions(Option $option, SubElement $subElement): array 
    { 
     return $this->getLeft($option, $subElement, Type::get(Type::DEPEND))->getResult(); 
    } 

    /** 
    * getRequiringOptionsExceptCurrent returns a Collection of Relations which require a Option, except the given Option. 
    * 
    * @param Option $option 
    * @param SubElement $subElement 
    * @return array 
    */ 
    public function getRequiringOptionsExceptCurrent(Option $option, SubElement $subElement): array 
    { 
     return $this->getLeft($option, $subElement, Type::get(Type::DEPEND), true)->getResult(); 
    } 

    /** 
    * getExceludedOptions returns a Collection of Relations which are excluded by the given Option. 
    * 
    * @param Option $option 
    * @param SubElement $subElement 
    * @return array 
    */ 
    public function getExceludedOptions(Option $option, SubElement $subElement): array 
    { 
     return $this->getLeft($option, $subElement, Type::get(Type::EXCLUDE))->getResult(); 
    } 

    /** 
    * getExcludedByOptions returns a Collection of Relations which exclude the given Option. 
    * 
    * @param Option $option 
    * @param SubElement $subElement 
    * @return array 
    */ 
    public function getExcludedByOptions(Option $option, SubElement $subElement): array 
    { 
     return $this->getRight($option, $subElement, Type::get(Type::EXCLUDE))->getResult(); 
    } 

    /** 
    * getSelectedOptions returns a Collection of Relations which are selected by the given Option. 
    * 
    * @param Option $option 
    * @param SubElement $subElement 
    * @return array 
    */ 
    public function getSelectedOptions(Option $option, SubElement $subElement): array 
    { 
     return $this->getLeft($option, $subElement, Type::get(Type::SELECT))->getResult(); 
    } 

    /** 
    * getSelectedByOptions returns a Collection of Relations which select the given Option. 
    * 
    * @param Option $option 
    * @param SubElement $subElement 
    * @return array 
    */ 
    public function getSelectedByOptions(Option $option, SubElement $subElement): array 
    { 
     return $this->getRight($option, $subElement, Type::get(Type::SELECT))->getResult(); 
    } 
} 
/** 
* @ORM\Entity(repositoryClass="Acme\Domain\Entity\Option\RelationRepository") 
* @ORM\Table(name="acme_opties_relaties") 
*/ 
class Relation 
{ 
    /** 
    * @ORM\ManyToOne(targetEntity="Acme\Domain\Entity\Option\Option", inversedBy="relations") 
    * @ORM\JoinColumn(name="id_a", referencedColumnName="id") 
    * @ORM\Id() 
    */ 
    private $option; 

    /** 
    * @ORM\OneToOne(targetEntity="Acme\Domain\Entity\Option\Option", fetch="EAGER") 
    * @ORM\JoinColumn(name="id_b", referencedColumnName="id") 
    * @ORM\Id() 
    */ 
    private $relation; 
/** 
* Class Option 
* @package Acme\Domain\Entity\Option 
* @ORM\Entity(repositoryClass="OptionRepository") 
* @ORM\Table(name="acme_options") 
*/ 
class Option 
{  
    /** 
    * @var Collection 
    * @ORM\OneToMany(targetEntity="Acme\Domain\Entity\Option\Relation", mappedBy="option") 
    */ 
    private $relations; 

問題是關係和選項之間的連接不上r.option.id_a = option.id但在r.option.id_a <> X,它應該加入的ID和在哪裏適用<> X

回答

0

噢,我們仍然有大部分SQL可用。所以,把它改爲:

private function getQuery(Option $option, SubElement $subElement, Type $type, string $direction, bool $inversed): Query 
{ 
    $direction = strtolower($direction); 

    $this->validateDirection($direction); 

    $query = 'select r, option, relation 
       from Acme\Domain\Entity\Option\Relation r 
       join r.option option 
       join r.relation relation 
       join option.subGroups osg 
       where osg in (:subGroup) 
       and option.project = :project 
       and r.type = :type 
       '; 

    $query = $this->addDirectionWhere($query, $direction, $inversed); 

    $subGroups = iterator_to_array($subElement->getElement()->getSubGroups()); 

    $q = $this->_em->createQuery($query); 
    $q->setParameter(':type', $type->getValue()) 
     ->setParameter(':option', $option->getId()) 
     ->setParameter(':project', $option->getProject()) 
     ->setParameter(':subGroup', $subGroups); 

    return $q; 
} 

我還是很開放的知道什麼是相當於將全光照QueryBuilder。因爲這是我的偏好。