mysql - 在 Doctrine2 中使用 SQL 中的 RAND() 函数

标签 mysql symfony doctrine-orm dql doctrine-query

我已经坚持了大约 10 个小时

我需要使用这个查询(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() 函数

<?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()';
    }
}

//配置.yml

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

问题是我一直收到这个错误:

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

RAND()源码出处:

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

如何从配置中添加:

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

DQL添加函数示例

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

编辑: 经过进一步研究,我发现 dql 不支持按函数排序: 来源: 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 值

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

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

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() 函数会降低服务器速度(在我们的例子中甚至会导致服务器崩溃)

最佳答案

您可以使用来自 Controller 的 native SQL 查询

$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/

关于mysql - 在 Doctrine2 中使用 SQL 中的 RAND() 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23112845/

相关文章:

php - WordPress 类别侧边栏

php - 由于缺少撇号 Doctrine 无法运行固定装置? (交响乐 2)

php - Symfony 安装缺少的供应商库

php - 重置学说 2 ID

transactions - MySQL import sqldump 成功回滚失败

mysql - 联合所有|合并具有相同列和表的 2 个查询

symfony - 如何覆盖供应商捆绑配置?

php - 如何用教义随机选择

mysql - 在MySql文档主页中定义删除

php - mailgun - 发送带有附件的邮件