简体   繁体   中英

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

What I actually need: returning records from the last month with QueryBuilder in Symfony2

OR in other words: converting following MySQL query to Doctrine QueryBuilder

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

What i did:

$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();

Result:

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"
  }
}

It returns but only records at the beginning of the table.

DATE_DIFF() returns the time between two dates. I think you have to use the DATE_SUB() function.

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

you can directly use mysql ' INTERVAL 1 MONTH' to get last one month data:

   $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();

Hope it helps....

I just registered my own 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

Query

$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();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM