【问题标题】:Symfony Doctrine Native Query Result Mapping Joining Subquery selectSymfony Doctrine Native Query 结果映射 Joining Subquery select
【发布时间】:2016-10-13 13:46:45
【问题描述】:

当我尝试映射加入子查询选择的结果时,我遇到了 symfony 和教义创建本机查询的问题。我得到前连接字段的空结果。 ad.availability 为 null 。

基本上我有 2 个表活动和活动日期。我需要获得每个活动的最低价格。 SQL 工作正常。但卡在映射中。

有什么想法吗?

谢谢

$rsm = new ResultSetMapping;
$rsm->addEntityResult('ActivityBundle:Activity', 'ac');
$rsm->addEntityResult('ActivityBundle:ActivityDate', 'ad');
$rsm->addFieldResult('ac', 'id', 'id');
$rsm->addFieldResult('ac', 'title', 'title');
$rsm->addFieldResult('ad','availability','availability');


$sql = 'SELECT 
            ac.id,
            ac.title,
            ac.price,
            ad.availability
        FROM
            activities ac
        LEFT JOIN
            (SELECT 
                id,
                date,
                price,
                activity_id,
                availability
            FROM
                activity_dates a
            WHERE
                price = (
                    SELECT 
                        MIN(price)
                    FROM
                        activity_dates b
                    WHERE
                        b.activity_id = a.activity_id
                )
            ) ad
        ON
            ad.activity_id =  ac.id';


$query = $this->_em->createNativeQuery($sql, $rsm)
    ->setHint(
        \Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER,
        'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker'
    )
    ->setHint(
        \Gedmo\Translatable\TranslatableListener::HINT_INNER_JOIN,
        true
    );

【问题讨论】:

  • 如果您在没有教义的情况下运行查询手动填写值,它会返回您期望的结果吗?
  • 是的。 sql 查询返回正确的值。

标签: symfony doctrine-orm


【解决方案1】:

让我们从简化查询开始:

SELECT ac.id, ac.title, ac.price, ad.availability
FROM activities ac
LEFT JOIN activity_dates ad
    ON ad.activity_id = ac.id
LEFT JOIN activity_dates ad2
    ON ad2.activity_id = ad.activity_id
        AND ad2.price < ad.price
WHERE ad2.price IS NULL

activity_dates 的自联接将尝试从 ad2 中获取价格低于 ad 中的记录。当 ad 中的价格是可用的最低价格时,这当然会失败,因此来自 ac2 的记录将为空。这就是我们可以用来通过ad2.price IS NULL 减少结果的方法。

我不太明白:在您的查询中,您比较了活动日期的价格,但选择了活动的价格。如果您想要每个活动的最低价格,您需要比较活动的价格,而不是活动日期。或者,如果您想要最便宜的 activity_date,则需要选择 ad.price。也许这只是一个错字...

无论如何:通过这个简化的查询,您应该能够以有用的方式创建您的实体,然后只需使用学说的查询功能。此处无需进行自定义查询。

有关自联接的参考,请参阅教义文档:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#one-to-one-self-referencing

或者也许这个 SO 帖子: Doctrine 2 Self Join Query

基本上它归结为这样的查询(从 Symfony 3 项目中采用):

$query = $this->createQueryBuilder('ac');
$query->select('ac.id, ac.title, ac.price, ad.availability')
    ->leftJoin('ac.activityDates', 'ad')
    ->leftJoin('ad.selfJoin', 'ad2', Join::WITH, 'ad2.price < ad.price')
    ->where(
        $query->expr()->isNull('ad2.price')
    );
$result = $query->getQuery()->getResult(AbstractQuery::HYDRATE_ARRAY);

【讨论】:

  • 感谢您的回答,我会尽力告诉您结果。关于活动和日期,每个活动在不同的日子有不同的价格,
  • 好吧,在这种情况下,我个人希望看到 ad.price。但这取决于你,只有很小的变化。简化有效果吗?
  • @Never:如果我的回答帮助您解决了问题,请考虑将其标记为已接受的答案或至少对其进行投票。如果没有,请随时添加 cmets,以便我可以帮助您解决任何问题。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-27
  • 2016-09-28
  • 2020-01-06
  • 1970-01-01
  • 1970-01-01
  • 2019-03-28
相关资源
最近更新 更多