这是我如何查询我的数据库的一些话
$query = $qb->select('w')
->from('DbEntities\Entity\Word', 'w')
->where('w.indictionary = 0 AND w.frequency > 3')
->orderBy('w.frequency', 'DESC')
->getQuery()
->setMaxResults(100);
我使用的MySQL,我想获得符合条件的随机行中,我会通过我的查询RAND()使用顺序。
我发现这个类似的问题,这基本上意味着,因为ORDER BY RAND原则中不支持,你可以随机主键代替。 但是,这不能在我的情况下这样做,因为我有一个搜索条件和where子句所以,不是每一个主键,将满足该条件。
我还发现了一个代码片段表明您使用OFFSET随机化这样的行:
$userCount = Doctrine::getTable('User')
->createQuery()
->select('count(*)')
->fetchOne(array(), Doctrine::HYDRATE_NONE);
$user = Doctrine::getTable('User')
->createQuery()
->limit(1)
->offset(rand(0, $userCount[0] - 1))
->fetchOne();
我有点困惑,这是否会帮助我在我的情况还是不解决缺乏支持顺序随机。 我是不是能够setMaxResult后增加所抵消。
任何想法,这可怎么实现的?
Answer 1:
该学说的团队是不是愿意来实现此功能 。
有几种解决方案,您的问题,每个都具有其自身的缺点:
- 添加自定义数字功能 :看到这个DQL RAND()函数
(如果你有很多的匹配行可能会慢) - 使用原生查询
(我个人尽量避免这种解决方案,我发现很难维持) - 首先发出原始SQL查询来获得一些随机的ID,然后使用DQL
WHERE x.id IN(?)
来加载相关联的对象,通过传递ID的数组作为参数。
该解决方案包括两个单独的查询,但可能给比第一个解决方案更好的性能(其他原材料SQL技术比ORDER BY RAND()
存在,在这里我就不详细介绍它们,你会发现这个网站上的一些很好的资源)。
Answer 2:
跟着这些步骤:
在您的项目定义一个新类:
namespace My\Custom\Doctrine2\Function;
use Doctrine\ORM\Query\Lexer;
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
:
doctrine:
orm:
dql:
numeric_functions:
Rand: My\Custom\Doctrine2\Function\Rand
直接使用它:
$qb->addSelect('RAND() as HIDDEN rand')->orderBy('rand');
Answer 3:
在什么哈桑Magdy萨阿德行建议 ,你可以使用流行的DoctrineExtensions库:
在这里看到的MySQL执行: https://github.com/beberlei/DoctrineExtensions/blob/master/src/Query/Mysql/Rand.php
# config.yml
doctrine:
orm:
dql:
numeric_functions:
rand: DoctrineExtensions\Query\Mysql\Rand
在学说ORM的2.6.x-dev的测试,可以再真正做到:
->orderBy('RAND()')
Answer 4:
或者你可以做到这一点 - >
$words = $em->getRepository('Entity\Word')->findAll();
shuffle($words);
当然,如果你有很多记录谨慎所以使用这将是非常低效的。
Answer 5:
原则2不支持ORDER BY RAND(),但我发现这个文章,其中包含的修补程序,这是问题。
Answer 6:
为什么不使用资料库?
<?php
namespace Project\ProductsBundle\Entity;
use Doctrine\ORM;
class ProductRepository extends ORM\EntityRepository
{
/**
* @param int $amount
* @return Product[]
*/
public function getRandomProducts($amount = 7)
{
return $this->getRandomProductsNativeQuery($amount)->getResult();
}
/**
* @param int $amount
* @return ORM\NativeQuery
*/
public function getRandomProductsNativeQuery($amount = 7)
{
# set entity name
$table = $this->getClassMetadata()
->getTableName();
# create rsm object
$rsm = new ORM\Query\ResultSetMapping();
$rsm->addEntityResult($this->getEntityName(), 'p');
$rsm->addFieldResult('p', 'id', 'id');
# make query
return $this->getEntityManager()->createNativeQuery("
SELECT p.id FROM {$table} p ORDER BY RAND() LIMIT 0, {$amount}
", $rsm);
}
}
Answer 7:
混洗可以在查询(阵列)结果来完成,但是改组不随机挑选。
为了从实体随机挑选我喜欢做这在PHP中,这可能会减缓随机挑选,但它可以让我继续测试我在做什么,使最终的调试更容易控制。
下面的例子将所有的ID从所述实体到一个数组,我可以然后在PHP使用“随机治疗”。
public function getRandomArt($nbSlotsOnPage)
{
$qbList=$this->createQueryBuilder('a');
// get all the relevant id's from the entity
$qbList ->select('a.id')
->where('a.publicate=true')
;
// $list is not a simple list of values, but an nested associative array
$list=$qbList->getQuery()->getScalarResult();
// get rid of the nested array from ScalarResult
$rawlist=array();
foreach ($list as $keyword=>$value)
{
// entity id's have to figure as keyword as array_rand() will pick only keywords - not values
$id=$value['id'];
$rawlist[$id]=null;
}
$total=min($nbSlotsOnPage,count($rawlist));
// pick only a few (i.e.$total)
$keylist=array_rand($rawlist,$total);
$qb=$this->createQueryBuilder('aw');
foreach ($keylist as $keyword=>$value)
{
$qb ->setParameter('keyword'.$keyword,$value)
->orWhere('aw.id = :keyword'.$keyword)
;
}
$result=$qb->getQuery()->getResult();
// if mixing the results is also required (could also be done by orderby rand();
shuffle($result);
return $result;
}
Answer 8:
我希望这会帮助别人:
$limit = $editForm->get('numberOfQuestions')->getData();
$sql = "Select * from question order by RAND() limit $limit";
$statement = $em->getConnection()->prepare($sql);
$statement->execute();
$questions = $statement->fetchAll();
注意这里的表的问题是一个的appbundle:问题的实体。 相应地更改的细节。 问题的数量从编辑的形式拍摄,请务必检查表单生成器的变量,并相应地使用。
Answer 9:
@克日什托夫的解决方案是最好恕我直言这里,但RAND()是大型查询速度很慢,所以我更新@ Krysztof的解决方案,得到较少的“随机”的结果,但他们仍然足够随机。 通过这个答案的启发https://stackoverflow.com/a/4329492/839434 。
namespace Project\ProductsBundle\Entity; use Doctrine\ORM; class ProductRepository extends ORM\EntityRepository { /** * @param int $amount * @return Product[] */ public function getRandomProducts($amount = 7) { return $this->getRandomProductsNativeQuery($amount)->getResult(); } /** * @param int $amount * @return ORM\NativeQuery */ public function getRandomProductsNativeQuery($amount = 7) { # set entity name $table = $this->getClassMetadata() ->getTableName(); # create rsm object $rsm = new ORM\Query\ResultSetMapping(); $rsm->addEntityResult($this->getEntityName(), 'p'); $rsm->addFieldResult('p', 'id', 'id'); # sql query $sql = " SELECT * FROM {$table} WHERE id >= FLOOR(1 + RAND()*( SELECT MAX(id) FROM {$table}) ) LIMIT ? "; # make query return $this->getEntityManager() ->createNativeQuery($sql, $rsm) ->setParameter(1, $amount); } }
Answer 10:
也许最简单的(但不一定是最聪明的)的方式来得到一个对象的结果尽快在你的仓库类将实现这一点:
public function findOneRandom()
{
$className = $this->getClassMetadata()->getName();
$counter = (int) $this->getEntityManager()->createQuery("SELECT COUNT(c) FROM {$className} c")->getSingleScalarResult();
return $this->getEntityManager()
->createQuery("SELECT ent FROM {$className} ent ORDER BY ent.id ASC")
->setMaxResults(1)
->setFirstResult(mt_rand(0, $counter - 1))
->getSingleResult()
;
}
Answer 11:
对我来说,最有用的方法是创建两个数组在那里我说,订单类型和实体的不同属性。 例如:
$order = array_rand(array(
'DESC' => 'DESC',
'ASC' => 'ASC'
));
$column = array_rand(array(
'w.id' => 'w.id',
'w.date' => 'w.date',
'w.name' => 'w.name'
));
你可以像标准添加更多的条目数组$列。
之后,你可以建立学说加$柱和$订单里面查询 - >排序依据。 例如:
$query = $qb->select('w')
->from('DbEntities\Entity\Word', 'w')
->where('w.indictionary = 0 AND w.frequency > 3')
->orderBy($column, $order)
->getQuery()
->setMaxResults(100);
通过这种方式提高了我的应用程序的性能。 我希望这可以帮助别人。
Answer 12:
首先从数据库表中获取的MAX值,然后用这个作为PHP偏移,即$偏移量= mt_rand(1,$ maxId)
Answer 13:
我知道这是一个老问题。 但我用以下解决方案来获得随机行。
使用EntityRepository方法:
public function findOneRandom()
{
$id_limits = $this->createQueryBuilder('entity')
->select('MIN(entity.id)', 'MAX(entity.id)')
->getQuery()
->getOneOrNullResult();
$random_possible_id = rand($id_limits[1], $id_limits[2]);
return $this->createQueryBuilder('entity')
->where('entity.id >= :random_id')
->setParameter('random_id', $random_possible_id)
->setMaxResults(1)
->getQuery()
->getOneOrNullResult();
}
Answer 14:
只需添加以下内容:
->orderBy('RAND()')
文章来源: How to select randomly with doctrine