使用SQL中的RAND()函数与Doctrine2

问题描述:

我已经被困住了大约10个小时

I've been stuck with this for about 10 hours

我需要使用这个查询(ORDER BY RAND的优化版本)

I need to use this query (an optimized version of ORDER BY RAND)

public function findAllRandom()
{
   return $this->getEntityManager()
    ->createQuery(
        'SELECT p FROM GabrielUploadBundle:Image p WHERE RAND() < 0.0001 ORDER BY RAND() LIMIT 20')
    ->getResult();
}

当然,由于我使用DQL,我需要实现RAND )函数

And of course since I'm using DQL I need to implement the RAND() function

<?php
namespace Gabriel\UploadBundle\DoctrineFunctions;
use Doctrine\ORM\Query\Lexer;

/**
 * RandFunction ::= "RAND" "(" ")"
 */
class Rand extends \Doctrine\ORM\Query\AST\Functions\FunctionNode
{ 
    public function parse(\Doctrine\ORM\Query\Parser $parser)
    {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);
        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        return 'RAND()';
    }
}

// Config.yml

//Config.yml

orm:
(...)
    dql:
       numeric_functions:
         Rand: Gabriel\UploadBundle\DoctrineFunctions\Rand

问题是我不断得到这个错误:

The problem is I keep getting this error:

[Syntax Error] line 0, col 77: Error: Expected end of string, got '('

RAND()源代码的来源:

The source of the RAND() source code:


https://gist.github.com/Ocramius/919465

如何从配置中添加:


http://symfony.com/doc/current/cookbook/doctrine/custom_dql_functions.html

演示关于向DQL添加功能

demo about adding functions to DQL

http://punkave.com/window/2012/07/24/for-the-php-crowd-adding-custom-functions-to-doctrine-2-dql

编辑:
经过进一步的研究,我发现dql中不支持按函数排序:
source :
http://docs.doctrine-project.org/en/2.1/reference/faq.html#can-i-sort-by-a-function-for- example-order-by-rand-in-dql

要解决此问题,可以添加HIDDEN值

To work around this the HIDDEN value can be added

public function findAllRandom()
{
   return $this->getEntityManager()
    ->createQuery(
        'SELECT p,RAND() AS HIDDEN rand FROM GabrielUploadBundle:Image p ORDER BY rand')
    ->getResult();
}

但由于某些原因,它不适用于WHERE子句

but for some reason it doesn't work with the WHERE clause

public function findAllRandom()
{
   return $this->getEntityManager()
    ->createQuery(
        'SELECT p,RAND() AS HIDDEN rand FROM GabrielUploadBundle:Image p WHERE rand < 0.00001 ORDER BY rand')
    ->getResult();
}

对于where子句的解决方案将不胜感激,每个人都知道使用ORDER BY RAND()函数可能会减慢服务器(在我们的情况下甚至崩溃)

A solution for the where clause would be appreciated, everyone knows that using the ORDER BY RAND() function can slow down the server (in our case even crash it)

您可以使用本机SQL查询从控制器

You can use a native SQL query from the controller

$em = $this->getDoctrine()->getManager();
$connection = $em->getConnection();
$statement = $connection->prepare("SELECT * FROM Image WHERE RAND()<(SELECT ((10/COUNT(*))*10) FROM Image) ORDER BY RAND() LIMIT 10");

$statement->execute();
$images = $statement->fetchAll();

基准测试结果
http://www.warpconduit.net/2011/03/23/selecting-a-random -record-using-mysql-benchmark-results /