如何使用 QueryBuilder 计算 CURRENT_DATE() 与上个月之间的天数差异?

How to calculate the difference in days between CURRENT_DATE() and the last month with QueryBuilder?

我真正需要的是: 在 Symfony2 中使用 QueryBuilder 返回上个月的记录

或者换句话说: 将以下 MySQL 查询转换为 Doctrine QueryBuilder

created_at >= DATE_FORMAT(NOW(), '%Y-%m-%d') - INTERVAL 1 MONTH

我做了什么:

$clicks = $clickRepo->createQueryBuilder('c')
        ->select('c.product, c.createdAt, c.title')
        ->addSelect('COUNT(c.product)')
        ->where('c.type = :pro')
            ->setParameter('pro', 'product')
        ->andWhere('c.createdAt >= DATE_DIFF(CURRENT_DATE(), :end)')
            ->setParameter('end', new \DateTime('-30 days'), \Doctrine\DBAL\Types\Type::DATETIME)
        ->andWhere('c.shop != :null')
            ->setParameter('null', '0')
        ->andWhere('c.visible = :one')
            ->setParameter('one', '1')
        ->groupBy('c.product')
        ->setMaxResults(2)
        ->getQuery()->getResult();

结果:

array(1) {
  [0]=>
  array(4) {
    ["product"]=>
    int(3)
    ["createdAt"]=>
    object(DateTime)#3211 (3) {
      ["date"]=>
      string(26) "2016-02-19 13:27:45.000000"
      ["timezone_type"]=>
      int(3)
      ["timezone"]=>
      string(13) "Europe/Berlin"
    }
    ["title"]=>
    string(23) "Title BlaBla"
    ["clicks"]=>
    string(1) "2"
  }
}

它returns但只记录在table的开头。

你可以直接使用mysql'INTERVAL 1 MONTH'来获取最近一个月的数据:

   $clicks = $clickRepo->createQueryBuilder('c')
            ->select('c.product, c.createdAt, c.title')
            ->addSelect('COUNT(c.product)')
            ->where('c.type = :pro')
                ->setParameter('pro', 'product')
            ->andWhere('c.createdAt >= (NOW() - INTERVAL 1 MONTH)')

            ->andWhere('c.shop != :null')
                ->setParameter('null', '0')
            ->andWhere('c.visible = :one')
                ->setParameter('one', '1')
            ->groupBy('c.product')
            ->setMaxResults(2)
            ->getQuery()->getResult();

希望对您有所帮助....

DATE_DIFF() returns 两个日期之间的时间。我认为您必须使用 DATE_SUB() 函数。

->andWhere('c.createdAt >= DATE_SUB(CURRENT_DATE(), :end)')

我刚刚注册了自己的DQL function

DateAddFunction.php

# Bundle/ProductBundle/myDQL/DateAddFunction.php
<?php

namespace Bundle\ProductBundle\myDQL;

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

/**
 * DateAddFunction ::=
 *     "DATE_ADD" "(" ArithmeticPrimary ", INTERVAL" ArithmeticPrimary Identifier ")"
 */
class DateAddFunction extends FunctionNode
{
    public $firstDateExpression = null;
    public $intervalExpression = null;
    public $unit = null;

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

        $this->firstDateExpression = $parser->ArithmeticPrimary();

        $parser->match(Lexer::T_COMMA);
        $parser->match(Lexer::T_IDENTIFIER);

        $this->intervalExpression = $parser->ArithmeticPrimary();

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

        /* @var $lexer Lexer */
        $lexer = $parser->getLexer();
        $this->unit = $lexer->token['value'];

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

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        return 'DATE_ADD(' .
            $this->firstDateExpression->dispatch($sqlWalker) . ', INTERVAL ' .
            $this->intervalExpression->dispatch($sqlWalker) . ' ' . $this->unit .
            ')';
    }
}

config.yml

# app/config/config.yml
doctrine:
    orm:
        auto_generate_proxy_classes: "%kernel.debug%"
        auto_mapping: true
        dql:
            string_functions:
                DATEADD: \Bundle\ProductBundle\myDQL\DateAddFunction

查询

$clicks = $clickRepo->createQueryBuilder('c')
  ->select('c.product, c.createdAt, c.title')
  ->addSelect('COUNT(c.product)')
  ->where('c.type = :pro')
    ->setParameter('pro', 'product')
  ->andWhere('c.createdAt >= DATEADD(CURRENT_DATE(), INTERVAL :minusOne MONTH)')
    ->setParameter('minusOne', '-1')
  ->andWhere('c.shop != :null')
    ->setParameter('null', '0')
  ->andWhere('c.visible = :one')
    ->setParameter('one', '1')
  ->groupBy('c.product')
  ->setMaxResults(2)
  ->getQuery()->getResult();