【问题标题】:Unable to convert MySql query using doctrine DQL or QueryBuilder无法使用学说 DQL 或 QueryBuilder 转换 MySql 查询
【发布时间】:2015-10-11 08:47:11
【问题描述】:

我无法转换此查询:

SELECT c.title, COUNT(*),
(
    SELECT ba_thumb.link
    FROM ba_video
    INNER JOIN video_channel ON video_channel.video_id=ba_video.id
    INNER JOIN ba_thumb ON ba_thumb.video_id=video_channel.video_id
    INNER JOIN ba_channel ON ba_channel.id=video_channel.channel_id
    WHERE video_channel.channel_id=c.id
    ORDER BY ba_video.views DESC, ba_thumb.id ASC
    LIMIT 1
) AS ba_thumb_link
FROM ba_channel c
INNER JOIN video_channel ON video_channel.channel_id=c.id
INNER JOIN ba_video ON ba_video.id=video_channel.video_id
GROUP BY video_channel.channel_id
ORDER BY COUNT(*) DESC

进入 DQL 或使用 QueryBuilder。

我在 DQL 中尝试过:

return $this->_em->createQuery('
            SELECT c.title, COUNT(*),
             (
                SELECT t.link
                FROM BAVideoGalleryBundle:Video v
                INNER JOIN v.channels c 
                INNER JOIN v.thumbs t 
                WHERE c.id=mc.id
                ORDER BY v.views DESC, t.id ASC
                LIMIT 1
             )
             FROM BAVideoGalleryBundle:Channel mc
             INNER JOIN BAVideoGalleryBundle:Video mv
             GROUP BY mv.Channels.id
             ORDER BY COUNT(*) DESC')
             ->getResult();

我明白了:

“[语法错误] line 0, col 216: Error: Expected Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS, got 'LIMIT'”

我尝试使用 QueryBuilder :

$query = $this->getEntityManager()->createQueryBuilder()
    ->select('c.title, COUNT(*)')
    ->from('BAVideoGalleryBundle:Channel', 'mc')
    ->innerJoin('BAVideoGalleryBundle:Video', 'mv')
    ->groupBy('mv.Channels.id')
    ->orderBy('COUNT(*)', 'DESC');

$subquery = $this->getEntityManager()->createQueryBuilder()
    ->select('t.link')
    ->from('BAVideoGalleryBundle:Video', 'v')
    ->innerJoin('v.channels', 'c')
    ->innerJoin('v.thumbs', 't')
    ->where('c.id=mc.id')
    ->orderBy('v.views', 'DESC')
    ->orderBy('t.id', 'ASC')
    ->getQuery()
    ->getResult();

return $query->addSelect('('.$subquery->getDql().')')

但相关性不起作用,我明白了:

[语义错误] 第 0 行,第 105 列靠近“mc.id ORDER BY”:错误:“mc” 没有定义

【问题讨论】:

  • 检查您的应用程序/日志中的dev.log。或者检查你的 MySQL 通用查询日志,看看你的实际查询是从学说转换成什么的。
  • LIMIT 在 DQL 中不存在,你必须使用->setMaxResults(1)
  • 并使用 setFirstResult(带有 setMaxResults)。然后在查询结束时执行限制 0,10 .....->orderBy('t.id', 'ASC')->setFirstResult(0)->setMaxResults(1)

标签: php mysql symfony doctrine-orm doctrine


【解决方案1】:

在这种情况下,Doctrine ORM 可能会给您带来比它解决的问题更多的问题。你可以:

  1. 使用native query 和相关的ResultSetMapping 设置
  2. 将您的 SQL 查询重构为 Doctrine 可以在 DQL 中处理的内容。查看您拥有的查询,您可以通过多种不同的方式来执行此操作(例如,将子查询视为 FROM / JOIN 部分中的临时表),但我看不到 Doctrine DQL 允许的方式
  3. 使用 Doctrine DBAL 直接使用 SQL。看起来你正在使用$this->_em,这让我觉得你在EntityRepository 中,所以你可以这样做:$this->_em->getConnection() 得到DBAL connection,然后只做$conn->query()。显然,这样您就失去了 ORM(与数据库无关等)的好处,但您可以将 ORM 视为执行复杂查询的税收。

我知道这些都不是理想的,但根据经验,有时最好将 Doctrine ORM 推开以实现您的需求。

【讨论】:

  • 执行多个简单查询通常比具有多个连接和子选择的单个大查询更快。所以我同意@john-noel 的建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-25
  • 1970-01-01
  • 2015-11-20
  • 2012-10-21
  • 2016-02-29
相关资源
最近更新 更多