将查询转换为doctrine DQL

时间:2018-03-21 11:27:27

标签: doctrine-orm doctrine-query

我有很大的MySQL查询用于性能优化我在join语句中添加子查询。使用原始SQL一切正常。这是查询:

SELECT
    campaigns.id,
    campaigns.name,
    CONCAT(users.id, ' ', users.email) AS usersData,
    CONCAT(campaigns.cpm, ' ', currencies.currency_code) AS cpm,
    CONCAT(campaign_budgets.total_spend, ' ', currencies.currency_code) AS total_spend,
    creatives.impressionsCount,
    creatives.bidsCount,
    creatives.winsAmount,
    creatives.winsPercentage,
    creatives.creativeIds
FROM campaigns
INNER JOIN users  ON campaigns.user_id = users.id
INNER JOIN campaign_budgets ON campaigns.id = campaign_budgets.campaign_id
INNER JOIN currencies  ON campaigns.currency_type_id = currencies.id
LEFT JOIN (
    SELECT
        GROUP_CONCAT(creatives.id) as creativeIds,
        creatives.campaign_id,
        creatives.user_id,
        impressions.impressionsCount,
        bids.bidsCount,
        bids.winsAmount,
        bids.winsPercentage
    from creatives
        LEFT JOIN (
                      SELECT
                        count(impressions.id) as impressionsCount,
                          impressions.user_id,
                          impressions.creative_id
                      from impressions
                      GROUP BY impressions.user_id
                  ) as impressions ON creatives.user_id = impressions.user_id
        LEFT JOIN (
                      SELECT
                          count(bids.id) as bidsCount,
                          SUM(CASE WHEN bids.status = 'won' THEN 1 ELSE 0 END) AS winsAmount,
                          SUM(CASE WHEN bids.status = 'won' THEN 1 ELSE 0 END) / COUNT(bids.id) * 100 AS winsPercentage,
                          bids.user_id,
                          bids.creative_id
                      from bids
                      GROUP BY bids.user_id
                  ) as bids ON creatives.user_id = bids.user_id
    GROUP BY creatives.campaign_id
    ) as creatives ON  campaigns.id  = creatives.campaign_id
GROUP BY campaigns.id

如果有可能,我需要以某种方式将其转换为Doctrine DQL。在将子查询添加到join语句时,我遇到了一个问题。这是我的代码:

          $columns = [
            'campaign.id',
            'campaign.name',
            'CONCAT(owner.id,\' \', owner.email) as ownerEmail',
            'CONCAT(campaign.cpm,\' \', currency.currencyCode) as cpm',
            'CONCAT(budget.totalSpend,\' \', currency.currencyCode) as totalSpend',
            'COUNT(imp.id) as impressionsCount',
            'COUNT(bid.id) as totalBidsCount',
            'SUM(case when bid.status = \'won\' then 1 else 0 end) as winsAmount',
            'SUM(case when bid.status = \'won\' then 1 else 0 end)/COUNT(bid.id)*100 as winsPercentage',
        ];
        $bids = $this->_em->getRepository(Bid::class)
            ->createQueryBuilder('bids')
            ->select([
                'count(bids.id) as bidsCount',
                'SUM(CASE WHEN bids.status = \'won\' THEN 1 ELSE 0 END) AS winsAmount',
                'SUM(CASE WHEN bids.status = \'won\' THEN 1 ELSE 0 END) / COUNT(bids.id) * 100 AS winsPercentage',
                'bids.userId',
                'bids.creativeId'
            ])->getDQL();
        $impressions = $this->_em->getRepository(Impression::class)
            ->createQueryBuilder('imp')
            ->select([
                'count(imp.id) as impressionsCount',
                'imp.userId',
                'imp.creativeId'
            ])->getDQL();
        $creative = $this->_em->getRepository(Creative::class)                ->createQueryBuilder('cr')->select('cr.id')
            ->select([
                'GROUP_CONCAT(cr.id) as creativeIds',
                'cr.campaignId',
                'cr.userId',
                'impressions.impressionsCount',
                'bids.bidsCount',
                'bids.winsAmount',
                'bids.winsPercentage'
            ])
            ->leftJoin(Impression::class, sprintf('(%s) as imp', $impressions), Expr\Join::WITH, 'imp.id = cr.userId')
            ->leftJoin(Bid::class, sprintf('(%s) as bid', $bids), Expr\Join::WITH, 'bids.id = cr.userId')
            ->getDQL();


        $query = $this->createQueryBuilder('campaign')
            ->select($columns);

        $query
            ->join('campaign.user', 'owner')
            ->join('campaign.campaignBudget', 'budget')
            ->join('campaign.currencyType', 'currency')
            ->leftJoin(Creative::class, sprintf('(%s) as creative', $creative), Expr\Join::WITH, 'campaign.id = cr.campaignId');

        $query->groupBy('campaign.id');
        $query->setMaxResults($limit);
        $query->setFirstResult($offset);

        return $query->getQuery()->useQueryCache(true)->getResult();

我收到错误[Syntax Error] line 0, col 626: Error: Expected Doctrine\ORM\Query\Lexer::T_IDENTIFIER, got '(',问题在于将子查询添加到join语句中。

我很感激任何帮助!

1 个答案:

答案 0 :(得分:0)

好的,我找到了一个使用DBAL而不是DQL的解决方案,使用this作为参考