学说 2 和 group_concat

Posted

技术标签:

【中文标题】学说 2 和 group_concat【英文标题】:doctrine2 and group_concat 【发布时间】:2011-12-13 10:36:07 【问题描述】:

我一直在查看 docs/google 并没有找到任何解决方案。

有没有什么方法可以在没有原生mysql的情况下使用doctrine2(DQL)来执行或模仿GROUP_CONCAT?

例如:

SELECT u.id, u.name, [GROUP_CONCAT(...)] AS user_messages
FROM models\Users u
LEFT JOIN models\Messages m
GROUP BY u.id

得到

GROUP_CONCAT(m.id,'|',m.title SEPARATOR ':')

现在我正在使用 createNativeQuery() 来运行它,但我正在寻找一个学说 2 的解决方案。

提前致谢

【问题讨论】:

【参考方案1】:

是的,这可以通过 Beberlei(Doctrine2 的核心开发者)的 DoctrineExtensions 实现。在学说 2 中,您可以通过扩展 functionNode 类来定义自己的查询表达式。

最简单的方法是在项目中包含 DoctrineExtensions 库。我不知道您使用的是 Zend Framework 还是 Symfony 或任何其他框架,因此无法帮助您嵌入它。

您可以在此处查看 DoctrineExtensions:

https://github.com/beberlei/DoctrineExtensions

以及分组功能:

https://github.com/beberlei/DoctrineExtensions/blob/master/src/Query/Mysql/GroupConcat.php

请注意,您应该使用 GroupConcat 作为函数名,而不是像 MySQL 中那样使用 GROUP_CONCAT。

希望对你有帮助!

【讨论】:

正是我想要的。顺便说一句,我正在使用代码点火器 atm,但我想我会设法集成它。非常感谢【参考方案2】:

这里是完整的支持版本:

// -------------------------------------------------
// Complete support of GROUP_CONCAT in Doctrine2
// -------------------------------------------------
// Original Article: http://habrahabr.ru/post/181666/
// Automated translation to English: http://sysmagazine.com/posts/181666/ 
// Original github commit: https://github.com/denisvmedia/DoctrineExtensions/blob/d1caf21cd7c71cc557e60c26e9bf25323a194dd1/lib/DoctrineExtensions/Query/Mysql/GroupConcat.php

/**
 * DoctrineExtensions Mysql Function Pack
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to kontakt@beberlei.de so I can send you a copy immediately.
 */

namespace DoctrineExtensions\Query\Mysql;

use Doctrine\ORM\Query\AST\Functions\FunctionNode,
    Doctrine\ORM\Query\Lexer;

/**
 * Full support for:
 *
 * GROUP_CONCAT([DISTINCT] expr [,expr ...]
 *              [ORDER BY unsigned_integer | col_name | expr
 *                  [ASC | DESC] [,col_name ...]]
 *              [SEPARATOR str_val])
 *
 */
class GroupConcat extends FunctionNode

    public $isDistinct = false;
    public $pathExp = null;
    public $separator = null;
    public $orderBy = null;

    public function parse(\Doctrine\ORM\Query\Parser $parser)
    
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);

        $lexer = $parser->getLexer();
        if ($lexer->isNextToken(Lexer::T_DISTINCT)) 
            $parser->match(Lexer::T_DISTINCT);

            $this->isDistinct = true;
        

        // first Path Expression is mandatory
        $this->pathExp = array();
        $this->pathExp[] = $parser->SingleValuedPathExpression();

        while ($lexer->isNextToken(Lexer::T_COMMA)) 
            $parser->match(Lexer::T_COMMA);
            $this->pathExp[] = $parser->StringPrimary();
        

        if ($lexer->isNextToken(Lexer::T_ORDER)) 
            $this->orderBy = $parser->OrderByClause();
        

        if ($lexer->isNextToken(Lexer::T_IDENTIFIER)) 
            if (strtolower($lexer->lookahead['value']) !== 'separator') 
                $parser->syntaxError('separator');
            
            $parser->match(Lexer::T_IDENTIFIER);

            $this->separator = $parser->StringPrimary();
        

        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    
        $result = 'GROUP_CONCAT(' . ($this->isDistinct ? 'DISTINCT ' : '');

        $fields = array();
        foreach ($this->pathExp as $pathExp) 
            $fields[] = $pathExp->dispatch($sqlWalker);
        

        $result .= sprintf('%s', implode(', ', $fields));

        if ($this->orderBy) 
            $result .= ' ' . $sqlWalker->walkOrderByClause($this->orderBy);
        

        if ($this->separator) 
            $result .= ' SEPARATOR ' . $sqlWalker->walkStringPrimary($this->separator);
        

        $result .= ')';

        return $result;
    



// -------------------------------------------------
// Example of usage:
// -------------------------------------------------
$query = $this->createQueryBuilder('c')
    ->select("
            c as company,
            GroupConcat(b.id, ';', b.headOffice, ';', b.city, ';', s.name
            ORDER by b.id
            SEPARATOR '|') AS branches
        ")->leftJoin('c.branches', 'b')
    ->leftJoin('b.country', 's')
    ->groupBy('c.id')
    ->setFirstResult(0)
    ->setMaxResults(10)
    ->getQuery();
$result = $query->getResult();

【讨论】:

他们盗用了我自己写的这个功能,请把学分改成这个:habrahabr.ru/post/181666(sysmagazine.com好像做了我文章的自动翻译)。

以上是关于学说 2 和 group_concat的主要内容,如果未能解决你的问题,请参考以下文章

电大16秋西方行政学说学习周期03任务_0001答案

使用错误表别名生成查询的学说

与学说映射学说 2 的关联失败

使用可翻译的学说和 Symfony 2 形式

跨数据库关系学说2和PHP

学说 2 文档示例中的拥有方和反方是啥