5
SELECT invoice.id, 
COUNT(slip.id),
SUM(projected_minutes)  OVER (PARTITION BY task.id) AS projected_minutes
FROM invoice
INNER JOIN task ON task.invoice_id = invoice.id
LEFT JOIN slip ON slip.task_id = task.id

上記のクエリはpostgresqlにあり、DQLに変換したいのですが、DQLでウィンドウ関数のドキュメントが見つかりません。これはDoctrineでネイティブにサポートされていますか、それともカスタムdql関数を作成する必要がありますか?

4

4 に答える 4

4

Doctrineではこのベンダー固有の機能はサポートされていません。カスタムDQL関数を作成するか、ネイティブSQLを使用します。

于 2013-03-26T20:39:07.017 に答える
2

コメントの1つで尋ねられたように、COUNT()OVER()のカスタム文字列関数を添付します

<?php

namespace Example\Doctrine\CustomFunctions;

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

/**
 * Class CountOverSql
 */
class CountOverSql extends FunctionNode
{
    /**
     * @var string
     */
    private $field;

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        return "COUNT(".$this->field->dispatch($sqlWalker).") OVER()";
    }

    public function parse(\Doctrine\ORM\Query\Parser $parser): void
    {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);
        $this->field = $parser->StringPrimary();
        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }
}

そして、あなたはこのコードをあなたの教義の構成に追加する必要があるだけです:

$entityManager->getConfiguration()->addCustomStringFunction('count_over', function ($name) use ($c) {
    return new Example\Doctrine\CustomFunctions\CountOverSql($name);
});

そしてそれを使用するには、次のコードをselectステートメントに追加します。

$queryBuilder->select('table_name', 'count_over(table_name.id)');

それが誰かを助けることを願っています。

于 2018-12-03T11:57:16.080 に答える
1

ウィンドウ関数クラスのわずかに異なるバージョン。ここでは任意の集計関数を使用でき、ウィンドウで「Order By」句を使用できるため、より一般的です。

use Doctrine\ORM\Query\AST\AggregateExpression;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\AST\OrderByClause;
use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\SqlWalker;

class Over extends FunctionNode
{
    /** @var AggregateExpression */
    private $functionExpr;

    /** @var OrderByClause */
    private $orderByExpr;

    /**
     * {@inheritdoc}
     *
     * @throws \Doctrine\ORM\Query\AST\ASTException
     */
    public function getSql(SqlWalker $sqlWalker): string
    {
        if (!empty($this->orderByExpr->orderByItems)) {
            return "{$this->functionExpr->dispatch($sqlWalker)} OVER ({$this->orderByExpr->dispatch($sqlWalker)})";
        }

        return "{$this->functionExpr->dispatch($sqlWalker)} OVER ()";
    }

    /**
     * @param Parser $parser
     *
     * @throws \Doctrine\ORM\Query\QueryException
     */
    public function parse(Parser $parser): void
    {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);
        $this->functionExpr = $parser->StringPrimary();
        $parser->match(Lexer::T_COMMA);
        $this->orderByExpr = $parser->OrderByClause();
        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }
}

そして、次のように使用します。

$aggregateQueryResult = $this->createQueryBuilder('agg')
      ->select('OVER(sum(agg.quantity), ORDER BY agg.date, agg.id) as aggregated_sum')
于 2019-03-21T19:19:05.027 に答える
0

これは、Doctrine2の未亡人関数機能を提供する拡張機能ですhttps://github.com/elshafey/doctrine-window-functions

次のように拡張機能を使用できます

// configure the extension first
$entityManager->getConfiguration()->addCustomStringFunction(
    'WINDOW',
    \Elshafey\DoctrineExtensions\WindowFunctions\Query\Mysql\Window::class
);

// use your window function formula
SELECT invoice.id, 
COUNT(slip.id),
WINDOW(SUM(projected_minutes))  OVER (PARTITION BY task.id) AS projected_minutes
FROM invoice
INNER JOIN task ON task.invoice_id = invoice.id
LEFT JOIN slip ON slip.task_id = task.id
于 2020-09-19T23:52:01.770 に答える