我在尝试重新创建以下查询时遇到问题:
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&lt;&gt;上。 X,它应该加入id并在应用&lt;&gt;的地方加入X
答案 0 :(得分: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
中的等价物。因为这有我的偏好。