Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/symfony/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Symfony “条令查询生成器”;介于;表达式和子查询_Symfony_Doctrine Orm_Query Builder - Fatal编程技术网

Symfony “条令查询生成器”;介于;表达式和子查询

Symfony “条令查询生成器”;介于;表达式和子查询,symfony,doctrine-orm,query-builder,Symfony,Doctrine Orm,Query Builder,我正试图用Doctrine的查询生成器创建一个相当复杂的查询(我使用的是Doctrine 2.2)。在这个模型中,我有一个Distributor类和一个具有一对多关系的DistributorVisit类。每次代表访问分销商时,都会在Distributor Visite表中添加一行新的访问日期。可以找到这两个表的ER图 现在,我希望能够根据分销商的上次访问日期筛选分销商。因此,用户输入一个日期范围(上次访问开始日期和上次访问目的日期),并列出上次访问日期介于这两个日期之间的分销商。我使用的是Doc

我正试图用Doctrine的查询生成器创建一个相当复杂的查询(我使用的是Doctrine 2.2)。在这个模型中,我有一个
Distributor
类和一个具有一对多关系的
DistributorVisit
类。每次代表访问分销商时,都会在
Distributor Visite
表中添加一行新的访问日期。可以找到这两个表的ER图

现在,我希望能够根据分销商的上次访问日期筛选分销商。因此,用户输入一个日期范围(上次访问开始日期和上次访问目的日期),并列出上次访问日期介于这两个日期之间的分销商。我使用的是Doctrine的查询生成器,因为我在过滤器中执行了很多其他条件查询,我发现面向对象的方法在这种情况下工作得最好。以下是我在
DistributorRepository
课程中所做的:

$qb = $this->getEntityManager()->createQueryBuilder()
     ->select('o')
     ->from('MyBundle:Distributor', 'o');

// Lots of 'andWhere's here

$qbv = $this->getEntityManager()->createQueryBuilder();

$qb->andWhere($qb->expr()->between(

    $qbv->select($qbv->expr()->max('v.visitDate'))
        ->from('MyBundle:DistributorVisit', 'v')
        ->join('MyBundle:Distributor', 'o2',
            Join::WITH,
            $qbv->expr()->andX(
                $qbv->expr()->eq('o2.id', 'v.distributorId'),
                $qbv->expr()->eq('o2.id', 'o.id')
            ))
        ->getDQL(),

    $filter->getLastVisitFrom()->getTimestamp(),
    $filter->getLastVisitTo()->getTimestamp()
));
这给了我以下错误:

[Syntax Error] line 0, col 83: Error: Expected Literal, got 'SELECT'
我猜这是因为查询生成器在我的子选择所在的位置需要一个文本,但是子查询的结果应该是一个文本,对吗?可能是因为查询生成器没有相应地添加括号


非常感谢您的帮助。

我猜您当前的DQL如下所示:

SELECT ..
FROM ..
WHERE SELECT .. FROM .. BETWEEN .. AND ..
SELECT ..
FROM ..
WHERE (SELECT .. FROM ..) BETWEEN .. AND ..
但应该是这样的:

SELECT ..
FROM ..
WHERE SELECT .. FROM .. BETWEEN .. AND ..
SELECT ..
FROM ..
WHERE (SELECT .. FROM ..) BETWEEN .. AND ..
为了修复代码,我将子查询的dql放在括号内:

$subQueryDQL = $qbv->select($qbv->expr()->max('v.visitDate'))
    ->from('MyBundle:DistributorVisit', 'v')
    ...
    ->getDQL();

$qb->andWhere($qb->expr()->between(
    sprintf('(%s)', $subQueryDQL),
    $filter->getLastVisitFrom()->getTimestamp(),
    $filter->getLastVisitTo()->getTimestamp()
));

我现在通过以下方式解决了这个问题:

$qb = $this->getEntityManager()->createQueryBuilder()
    ->select('o')
    ->from('MyBundle:Distributor', 'o');

$qbdv = $this->getEntityManager()->createQueryBuilder();
$qbdv->select('MAX(dv2.visitDate)')
    ->from('MyBundle:DistributorVisit', 'dv2')
    ->where($qbdv->expr()->eq('dv2.distributor', 'o'));

$maxVisitDate = '('.$qbdv->getDQL().')';

$qb->leftJoin(
    'o.distributorVisits',
    'dv',
    Join::WITH,
    $qb->expr()->eq('dv.visitDate', $maxVisitDate)
);

$qb->andWhere(
    $qb->expr()->between(
        'dv.visitDate',
        ':dateFrom',
        ':dateTo'
    )
)
->setParameter('dateFrom', $filter->getLastVisitFrom())
->setParameter('dateTo', $filter->getLastVisitTo());
所以我基本上是这样做的:我将
DistributorVisit
表加入到
Distributor
表中,其中包含最长访问日期。诀窍在于,可以将(子)查询的DQL(
$qb1->getDQL()
)直接传递给一个条令表达式(
$qb2->expr()->eq('column',$qb1->getDQL()
)。我在上面的代码中使用了左连接来完成此操作。

我的案例:

$qb->andWhere(
"t.field BETWEEN (
    {$subQuerybuilder1->getDQL()}
  ) AND (
    {$subQuerybuilder2->getDQL()}
  )
");
得到:


有关如何查看生成的查询的详细信息,请参阅本文。从这里开始,如果您还没有弄明白,请在此处发布查询,以便我们更容易帮助您!:-)我实际上没有尝试您的解决方案,但它肯定朝着正确的方向发展。下面你们可以看到我是如何解决这个问题的,我相信这两个解决方案基本上是相同的。谢谢,这真的帮助了我。