Doctrine query building select MAX - symfony

I would like to select everything + MAX value and receive only rows having max values.
$query = $this->createQueryBuilder('s');
$query->where('s.challenge = :challenge')->setParameter('challenge', $challenge);
$query->groupBy('s.score');
$query->getQuery();
return $query->select('s.*, MAX(s.score) AS max_score')->getQuery()->getResult();
How could I achieve this in doctrine? I am getting an error that * property is not found. I have tried to select them all one by one but no luck either.
Goal is to achieve something like this
SELECT user, challenge, whateverelse, MAX(score) FROM users_scores_table GROUP BY user_id
Please help ;)

It's too late, but I write this for the records.
You can use "as HIDDEN" in SELECT statements to remove a field of the final result, this way you can use it for ordering or grouping without modifying result fields.
In your example:
$query = $this->createQueryBuilder('s');
$query->select('s, MAX(s.score) AS HIDDEN max_score');
$query->where('s.challenge = :challenge')->setParameter('challenge', $challenge);
$query->groupBy('s.user');
$query->setMaxResults($limit);
$query->orderBy('max_score', 'DESC');

Here is a final working query
$query = $this->createQueryBuilder('s');
$query->select('s, MAX(s.score) AS max_score');
$query->where('s.challenge = :challenge')->setParameter('challenge', $challenge);
$query->groupBy('s.user');
$query->setMaxResults($limit);
$query->orderBy('max_score', 'DESC');
return $query->getQuery()->getResult();

Related

Use the Doctrine's QueryBuilder to get Categories with a minimum number of products

I want to use the Doctrine's QueryBuilder to get Categories with a specified attribute and a number minimum of products inside. I precise that's the first time I use this Doctrine's function. I discovered that and I realized that it's so much powerful than basics repositories functions. I'm a very beginner with SQL because I used to use Repository's functions.
But I think I achieve this in pure SQL:
SELECT category.*,COUNT(*)
FROM category_product
INNER JOIN category ON category_product.category_id = category.id
WHERE category.name = 'region'
GROUP BY category_product.category_id HAVING COUNT(*) > 20
At the moment I'm totally lost with DQL construction. My Category and Product Entities both have a Many to Many relationship and I can't reach traducing this to Doctrine. I tried using the category_product table auto-generated by doctrine's but It doesn't want to access this table...
$qb = $this->createQueryBuilder('c');
$qb
->select('c')
->where("c.name = 'region'")
->innerJoin('c.products', 'p', 'WITH', 'COUNT(c.products) > :minimum')
->setParameter('minimum', $minimum);
dump($qb->getQuery(), $qb->getQuery()->getResult());
Each Time I uses a new construction I have Semantical errors I'm not able to correct...
Thanks a lot for your help
You could try some thing like here (piece of code from my working model)
$qb = $this->createQueryBuilder('c')
->select('c')
->where('c.name = region')
->addSelect('COUNT(c.products) AS counter')
->innerJoin('c.products', 'p')
->groupby('p.id')
->having('count(p.id) >= :minimum')
->setParameter('region', $region)
->setParameter('minimum', $minimum)
;
dump($qb->getQuery()->getResult());
related post: here
Ok Thanks to you I got it.
I shouldn't select the COUNT because I typed the return to be an Array of categories but it returned an array of arrays with contains the category and the count... I had to group by c too.
Thanks a lot for your help !
The answer is :
$qb = $this->createQueryBuilder('c')
->select('c')
->where('c.name = :region')
->innerJoin('c.products', 'p')
->groupBy('c')
->having('SIZE(c.products) > :minimum')
->setParameter('region', $region)
->setParameter('minimum', 20);

update an arrayResult of doctrine

i this query i get all of phones with certain condition
and one thing that i want after that is to set isFirstInstalled of all phones in this query to 1
also i want data of this query for api result
what is the most optimize way for that
the simplest way is using the result of the query in foreach and set one by one to 1 ?!
i want the result of my query before updating
$isFirstNotInstalledCases = $em->getRepository(User::class)
->createQueryBuilder('u')
->select("u.phone as phone")
->addSelect("u.isFirstInstalled as isFirstInstalled")
->where("u.phone IN (:phone)")
->andWhere("u.isFirstInstalled = :isFirstInstalled")
->setParameters(['isFirstInstalled'=>0,'phone'=>$phones])
->getQuery()
->getArrayResult();
Try to avoid foreach if you have not to do logic, use update better. Something like this:
$qb = $this->_em->createQueryBuilder();
$q = $qb->update('App\User', 'u')
->set('u.isFirstInstalled', 1))
->where("u.phone IN (:phone)")
->andWhere("u.isFirstInstalled = :isFirstInstalled")
->setParameters(['isFirstInstalled'=>0,'phone'=>$phones])
->getQuery();
$p = $q->execute();

Select AVG of rows using Query Builder

I want to select the average of columns 'note' from a table
'noteparagraphe' where
the id_paragraphe is a parameter ($ref), I tried this query but I'm getting nothing back !
$query=$this->get('doctrine.orm.entity_manager')
->createQuery('Select avg(n.note) from ParagrapheBundle:NoteParagraphe n
WHERE n.id_paragraphe = :idModele');
$query->setParameter('idModele', $ref);
$query->execute();
$avgNote = $query->getResult();
the SQL is : SELECT AVG(note) from note_paragraphe WHERE id_paragraphe=?
Use Query builder:
$query = $this->getDoctrine()->getRepository('ParagrapheBundle:NoteParagraphe');
$avgNote = $query->createQueryBuilder('n')
->select('avg(n.note)')
->where('n.id_paragraphe = :idModele')
->setParameter('idModele', $ref);
->getQuery();
See if that works - I haven't tried it, but I think it should work.

How I can Iterate into SUM result from doctrine query

I need some help about iterate over result in doctrine. This is my code for query:
$consulta = $em->createQuery('
SELECT bcr, SUM(bcr.volumenAlmacenado) as vol, SUM(bcr.pesoAlmacenado) as pes
FROM ResiduoBundle:BodegaContieneResiduo bcr
WHERE bcr.fechaIngreso BETWEEN :fechaP AND :fechaA AND bcr.fechaRetiro IS NULL
GROUP BY bcr.idResiduo
');
$consulta->setParameter('fechaA', $fechaActual);
$consulta->setParameter('fechaP', $fechaPasada);
return $consulta->getResult();
When I run in mysql return without problem. in symfony also get results. Now, when I tried to loop in twig I can't do, I think could be for my agregate functions in my query. I hope you can get me a clue or something about this. Grettings
You should added extension of mysql function SUM then you can use SUM function in doctrine query
another way you can direct execute your query or native query of doctrine
Try following query you can get result
$consulta = $em->executeQuery('SELECT bcr, SUM(bcr.volumenAlmacenado) as vol, SUM(bcr.pesoAlmacenado) as pes FROM ResiduoBundle:BodegaContieneResiduo bcr WHERE bcr.fechaIngreso BETWEEN :fechaP AND :fechaA AND bcr.fechaRetiro IS NULL GROUP BY bcr.idResiduo'),
array('fechaA'=> $fechaActual, 'fechaP' => $fechaPasada));
return $consulta->fetchAll();
You can also use native query of doctrine
use Doctrine\ORM\Query\ResultSetMapping;
$rsm = new ResultSetMapping();
$rsm->addEntityResult('ResiduoBundle:BodegaContieneResiduo', 'bcr');
$rsm->addFieldResult('bcr', 'idResiduo', 'idResiduo');
$rsm->addFieldResult('bcr', 'volumenAlmacenado', 'vol');
$rsm->addFieldResult('bcr', 'pesoAlmacenado', 'pes');
$sqlQuery = "SELECT bcr.idResiduo as idResiduo, SUM(bcr.volumenAlmacenado) as vol, SUM(bcr.pesoAlmacenado) as pes
FROM ResiduoBundle:BodegaContieneResiduo bcr
WHERE bcr.fechaIngreso BETWEEN :fechaP AND :fechaA
AND bcr.fechaRetiro IS NULL
GROUP BY bcr.idResiduo";
$query = $em->createNativeQuery($sqlQuery, $rsm)
->setParameter('fechaA', $fechaActual);
->setParameter('fechaP', $fechaPasada);
$query->getResult();

Symfony and Doctrine: order by time difference

I am trying to build a query that retrieves all the most recent and upcoming activities from database.
The entity activity has a field named date of type DateTime. So in my repository I was thinking of building something like this:
$query = $repository
->createQueryBuilder('a');
$query->orderBy( 'DATEDIFF( a.date, NOW())' , 'ASC');
$query->setMaxResults( 6 );
return $query;
Unfortunately I get the following error:
[Syntax Error] line 0, col 59: Error: Expected end of string, got '('
The Dql that is generated by my query:
SELECT a FROM MyBundle\Entity\Activity a ORDER BY DATEDIFF( a.date, NOW()) ASC
I also tried installing beberlei/DoctrineExtensions, but either it is not working or I was unable to configure it correctly.
Anyone has any suggestion?
Thanks in advance
date_diff si already implemented as Doctrine DQL statement as described here
for use as ordering statement I suggest you to use the HIDDEN select keyword as explained in this article
So your DQL is like this:
SELECT
a,
DATE_DIFF( a.date, CURRENT_TIMESTAMP() ) AS HIDDEN score
FROM MyBundle:Entity a
ORDER BY score
And add the max result on the query. Let me know if you need help to adapt as query builder statement
Hope this help
Why don't you just use
$query = $repository
->createQueryBuilder('a');
$query->orderBy( 'DATEDIFF( a.date, CURRENT_TIMESTAMP())' , 'ASC');
$query->setMaxResults( 6 );
return $query;
?

Resources