Get Avg value in Doctrine / symfony - symfony

i try to get AVG value in doctrine, in my Repositoru i do this:
public function getFotoSpecifica($idFoto) {
$q = $this->createQueryBuilder('f');
$q->leftJoin("f.foto_votata", 'v');
$q->where('f.id =:idFoto');
$q->andWhere('(f.foto_privata IS NULL OR f.foto_privata != 1)');
$q->andWhere('(f.foto_eliminata IS NULL OR f.foto_eliminata != 1)');
$q->expr()->avg('v.punteggio', true);
$q->setParameter('idFoto', $idFoto);
$dql = $q->getQuery();
$results = $dql->getArrayResult();
return $results;
}
but i don't find any value avg, i see all my object...i try to use createQuery in my controller but i have many errors like: Error: Invalid PathExpression. Must be a StateFieldPathExpression. ( this is a foreign key)
mySql query is:
SELECT profilo_id, proprietario_id, round(AVG( punteggio ),2) as avg_rate, SUM(punteggio) as score, foto_id, count(*) as numero_votanti
FROM prof_voto_foto
WHERE foto_id = ?

Assuming the variable name for the foreign key is named $foto and the entity is ProfVotoFoto
In your controller you can do something like this.
$em = $this->getDoctrine()->getManager();
$q=$em->createQuery("
SELECT profilo_id, proprietario_id, round(AVG( punteggio ),2) as avg_rate,
SUM(punteggio) as score, foto_id, count(*) as numero_votanti
FROM YourBundleName:ProfVotoFoto f
WHERE f.foto = :idFoto
")
->setPArameter('idFoto',$idFoto);
$averageResult = $q->getSingleResult();

You are forget to add a select statement to query. Also possible requires to add group by.
->addSelect('AVG(v.punteggio) as punteggio_avg')

Related

Need help for performing join Query with QueryBuilder

I got a working SQL query : select p.name, p.id from acv_project p join acv_product prod on prod.project_id = p.id where prod.weight <> 0 and p.green_user_id = 18
If i pass it into a `
$stmt = $em->getConnection()->prepare($rawSql);
$stmt->execute([]);
$projects = $stmt->fetchAll();
It works but i'd like to pass it by adding the "green_user_id" as a parameter and not always 18.
When i try with this code : `
$sql2 = "select p from ArtoAcvBundle:Project p join prod ArtoAcvBundle:Product on prod.project_id = p.id where prod.weight <> 0 and p.green_user_id =:userId";
$query2 = $em->createQuery($sql2)->setParameters(
array('userId' => $userId));
$projects = $query2->getResult();
I get [Semantical Error] line 0, col 48 near 'ArtoAcvBundle:Product': Error: Identification Variable prod used in join path expression but was not defined before.
And with QueryBuilder, i tried lots of thing but fails to understand how to write it.
Here are some links to my 2 Doctrine entities :
Entity Product
Entity Project
Thanks for help !
Proof with:
$sql2 = "select p from ArtoAcvBundle:Project p join ArtoAcvBundle:Product prod where prod.weight <> 0 and p.green_user_id =:userId";
Yep, great thanks for having found this solution. I continued to search and find there existed a bindValue() method in Doctrine.
So i passed my parameter with the raw SQL modified and it works
Example with QueryBuilder
// select p from ArtoAcvBundle:Project p join prod ArtoAcvBundle:Product on prod.project_id = p.id where prod.weight <> 0 and p.green_user_id =:userId
$query = $this->getRepository(Project::class)->createQueryBuilder('p');
$query->join('p.products' , 'prod')
->andWhere('prod.weight <> 0')
->andWhere('p.greenUser = :user')
->addParameter('user', $youruserEntity);
return $query->getQuery()->getResult();

Doctrine : SELECT a relationned entity

I have 2 entities :
LinkServInfra
Serv
LinkServInfra entity :
id
serv (relation OneToOne to Serv)
infra (ManyToOne to another entity)
Now, I'd like to get a list of Serv based on infra.
So I tried in LinkServInfraRepository :
$qb = $this->createQueryBuilder('s')
->select('DISTINCT s.serv')
->where('s.infra = :infra')
->setParameter('infra', $infra);
return $qb->getQuery()->getResult();
And I get an error :
[Semantical Error] near 'serv FROM': Error: InvalidPathExpression.
Must be a StateFieldPathExpression.
(I tried first without DISTINCT and tried with it based on answer found here).
The query seems to be good because it's :
SELECT DISTINCT s.serv
FROM MyBundle\Entity\LinkServInfra s
WHERE s.infra = :infra
How would you do?
Thanks!
Since the relation is ONLY in LinkServInfra and not in Serv :
I used the relation in LinkServInfra to do it...
public function filter($type, $etat, $infra){
$qb = $this->createQueryBuilder('l');
$qb->where(' l.infra = :infra ')
->setParameter('infra', $infra);
if( $type || $etat ){
$qb->join('l.serv', 's')
//where & setParameter for type
//where & setParameter for detail
}
And then where I call the function filter :
$entities = $em->getRepository('linkServInfra')->filter(//...
$servs = array();
foreach($entities as $entity){
$servs[] = $entity->getServ();
}
I guess it's not the cleanest solution but it's working...
I think you can not use DISTINCT on a relation, only for the root entity alias.
You should use Serv entity as root and join with LinkServInfra and infra entity through the 2nd. Something like:
$qb = $this->getDoctrine()
->getRepository(Serv::class)->createQueryBuilder('s')
->select('DISTINCT s')
->leftJoin("s.linkServInfra", "lsi")
->leftJoin("lsi.infra", "infra")
->where('infra.id = :infra')
->setParameter('infra', 1);
Alternatively, if the relation is unidirectional and you do not want to make it bidirectional, you can use a custom join:
use Doctrine\ORM\Query\Expr\Join;
$qb = $this->getDoctrine()
->getRepository(Serv::class)->createQueryBuilder('s')
->select('DISTINCT s')
->leftJoin(LinkServInfra::class, "lsi", Join::WITH, 'lsi.serv = s')
->leftJoin("lsi.infra", "infra")
->where('infra.id = :infra')
->setParameter('infra', 1);
References
How to JOIN without a relationship in Doctrine?

delete several rows where attribute = x

I need to delete all rows where the image_id = x applies
like this
DELETE FROM `ImageVoters` WHERE image_id =1
How do I do this using DQL?
Since im trying to delete several rows at once the remove() function won't work
EntityManager#remove() expects parameter 1 to be an entity object, array given.
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery('SELECT u FROM GabrielUploadBundle:ImageVoters u WHERE u.image_id = 1');
$db_imageactions = $query->getResult();
$em->remove($db_imageactions);
$em->flush();
This is the code that works
$qb = $em->createQueryBuilder();
$qb->delete('GabrielUploadBundle:ImageVoters', 'v')
->where($qb->expr()->eq('v.image_id', ':imageId'))
->setParameter('imageId', $current_imageId);
$qb->getQuery()->execute();
You could create an ORM queryBuilder, to create a clean/safe query object by using internal orm methods
$qb->delete('My\Image\Namespace\ImageVoters', 'ivoter')
->where($qb->expr()->eq('ivoter.image_id', ':imageId')
->setParameter('imageId', 1);
$qb->getQuery()->execute();
You can also execute any raw SQL like this:
$sql = "DELETE FROM ImageVoters WHERE image_id =".$image_id;
$q = $em->getConnection()->exec($sql);

Propel multiple-parameter binding in where() clause

I'm trying to run this query on Propel 1.6 with symfony 1.4.20.
I want to bind 2 parameters onto this subquery but its not working.
$paginas = PaginaQuery::create()
->where("pagina.id not in (select id from cliente_artista where cliente_artista.cliente_id = ? and cliente_artista.culture = ?)"
,array('XXX', 'en')
)
->limit(5)
->find();
This gives me the error:
Cannot determine the column to bind to the parameter in clause
I also found this post but there is no answer (https://groups.google.com/forum/?fromgroups=#!topic/propel-users/2Ge8EsTgoBg)
Instead of using placeholders. You may use $id and $culture:
//first, get an array of the id's
//define your vars
$id = $your_id_param;
$culture = 'en';
$cliente_artistas = ClienteArtistaQuery::create()
->select('id')
->distinct()
->filterByClienteId($id)
->filterByCulture($culture)
->find();
$paginas = PaginaQuery::create()
->where("pagina.id NOT IN ?", $cliente_artistas)
->limit(5)
->find();
If this has to be done in one query, recommend using raw sql and binding the parameters into the PDO statement (but then you lose the convenience of PropelObjectCollections):
public function getResultSet($id, $culture) {
$id = $id_param;
$culture = $culture_param;
$sql = <<<ENDSQL
SELECT * from pagina
WHERE id NOT IN (SELECT distinct id
FROM cliente_artista
WHERE cliente_id = ?
AND culture = ?
)
LIMIT 5
ENDSQL;
$connection = Propel::getConnection();
$statement = $connection->prepare($sql);
$statement->bindValue(1, $id);
$statement->bindValue(2, $culture);
$statement->execute();
$resultset = $statement->fetchAll(PDO::FETCH_ASSOC); // or whatever you need
if (! count($resultset) >= 1) {
// Handle empty resultset
}
return $resultset;
}
You could also write some query methods to use propel orm query methods. Ofcourse, the propel api is beneficial reference. There are several ways to do this. I have indicated one method here which should work for you.
EDIT:
Here's an idea on doing this as one query [since useSelectQuery() requires 'relation' name], this idea assumes tables are not related but that id's are:
$paginas = PaginaQuery::create()
->addJoin(PaginaPeer::ID, ClienteArtistaPeer::CLIENTE_ID, Criteria::LEFT_JOIN)
->where("ClienteArtista.Id <> ?", $id)
->where("ClienteArtista.Culture <> ?", $culture)
->select(array('your','pagina','column','array'))
->limit(5)
->find();

query with dateformat in where clause in symfony2

when I run a query with date in where clause, following error is showed...
[Syntax Error] line 0, col 129: Error: Expected known function, got 'DATE_FORMAT'
the query is given below
$query = $this->getEntityManager()->createQuery(
"SELECT a.id, a.amont, a.paymentDescrip, a.paymentType, a.paymentDate
FROM RegalSmsBundle:DailyTransaction a
WHERE DATE_FORMAT(a.paymentDate,'%Y-%m-%d') = :paymentDate
and a.students = :studentId"
)->setParameter('studentId', $studentId)
->setParameter('paymentDate','2013-03-11');
return $query->getResult();
Doctrine doesn't have DATE_FORMAT function defined by default. It's possible to Register Custom DQL Function.
But you can compare date easily (assuming a.paymentDate is of type date):
$query = $this->getEntityManager()->createQuery("
SELECT a.id, a.amont, a.paymentDescrip, a.paymentType, a.paymentDate
FROM RegalSmsBundle:DailyTransaction a
WHERE a.paymentDate = :paymentDate AND a.students = :studentId
")
->setParameter('studentId', $studentId)
->setParameter('paymentDate', new \DateTime('2013-03-11'))
;
return $query->getResult();
Edit: I prefer using querybuider to writing DQL. It would look like this:
$qb = $this->getEntityManager()->getRepository('RegalSmsBundle:DailyTransaction')->createQueryBuilder('a');
$qb
->select('a') // select whole entity
->where($qb->expr()->andX(
$qb->expr()->eq('a.paymentDate', ':paymentDate')
$qb->expr()->eq('a.students', ':studentId')
))
->setParameter('studentId', $studentId)
->setParameter('paymentDate', new \DateTime('2013-03-11'))
;
return $qb->getQuery()->getResult();

Resources