Need some help to translate query from createQuery() to queryBuilder() - symfony

I'm used to create query with createQuery() instead of queryBuilder, but I need to translate a query in a queryBuilder one to use in a EntityType to generate a form. Here is my query :
SELECT p FROM D2ECoreBundle:Player p,
D2ECoreBundle:LadderMatch lm,
D2ECoreBundle:PlayerComposition hpc
JOIN hpc.players hp,
D2ECoreBundle:PlayerComposition fpc
JOIN fpc.players fp
WHERE (lm.homePlayerComposition = hpc AND hp = p)
OR (lm.foreignPlayerComposition = fpc AND fp = p)
and here is what i thought it would be in queryBuilder but doesnt work :
$qb->select('p')
->from('D2ECoreBundle:Player', 'p')
->from('D2ECoreBundle:LadderMatch', 'lm')
->from('D2ECoreBundle:PlayerComposition', 'hpc')
->join('hpc.players', 'hp')
->from('D2ECoreBundle:PlayerComposition', 'fpc')
->join('fpc.players', 'fp')
->where('lm.homePlayerComposition = hpc' AND 'hp = p')
->orwhere('lm.foreignPlayerComposition = fpc' AND 'fp = p');
Does anyone know what I should change to have it working? Thanx for the answers!

When you query the DB with:
SELECT * FROM TableA T1, TableB T2 ....
in many implementations is the same as:
SELECT * FROM TableA T1 JOIN TableB T2 ON ... // this is INNER JOIN
So, instead of using from multiple times, do joins:
$qb->select('p')
->from('D2ECoreBundle:Player', 'p')
->join('p.ladderMatches', 'lm')
->join('p.playerComposition', 'hpc')
->join('hpc.players', 'hp')
->join('hp.playerCompossition', 'fpc')
->join('fpc.players', 'fp')
->where('lm.homePlayerComposition = hpc' AND 'hp = p')
->orwhere('lm.foreignPlayerComposition = fpc' AND 'fp = p');
Not sure if I got the relation correct but you get the point...

I eventually managed to do this. Here is my code :
$qb = $this->createQueryBuilder('lm')
->select('p')
->from('D2ECoreBundle:Player', 'p')
->join('lm.homePlayerComposition', 'hpc')
->join('hpc.players', 'hp')
->join('lm.foreignPlayerComposition', 'fpc')
->join('fpc.players', 'fp')
->where('lm.homePlayerComposition = hpc AND hp = p')
->orwhere('lm.foreignPlayerComposition = fpc AND fp = p');
return $qb;
And a very important thing, since I want to select player, but starting by the LadderMatch entity, I need to put this in LadderMatchRepository.php and not PlayerRepository.php like I did, because it affects the generat

Related

SQLITE ordering group_concat with a left join

I have the following query
let Query = "SELECT LEVELS1.ID, LEVELS1.NAME, GROUP_CONCAT(FRAMEWORKLEVELS1.NAME,'&/?') AS DATA FROM LEVELS1 LEFT JOIN FRAMEWORKLEVELS1 ON LEVELS1.ID = FRAMEWORKLEVELS1.LEVELID WHERE FRAMEWORKID = :ID GROUP BY FRAMEWORKID"
which produces the following
DATA = "Level1&/?Level4&/?Level2&/?Level3";
ID = 1;
NAME = "Title";
What i want to do though is order the GROUP_CONCAT but how do i do this in SQLITE?
I have found the following link
Sqlite group_concat ordering
but i can't work out how to get the left join in there
Thanks
Just get all the data you want, sort it, and then aggregate it:
SELECT ID,
Name,
group_concat(LevelName, '&/?') AS Data
FROM (SELECT Levels1.ID AS ID,
Levels1.Name AS Name,
FrameworkLevels1.Name AS LevelName
FROM Levels1
LEFT JOIN FrameworkLevels1 ON Levels1.ID = FrameworkLevels1.LevelID
WHERE FrameworkID = :ID
ORDER BY ...);

DQL - leftJoin() error: Expected Literal, got 'JOIN'

This code:
$builder->select('p')
->from('ProProposalBundle:Proposal', 'p')
->leftJoin('ProProposalBundle:Proposal:Vote', 'v')
->leftJoin('ProUserBundle:User', 'u')
->andWhere('v.proposal = p')
->andWhere('v.user = u')
->andWhere('v.decision = "in_favor" OR v.decision = "against"')
->andWhere('u = :user')
->setParameter('user', $options['user'])
->andWhere('p.community = :community')
->setParameter('community', $community)
->andWhere('p.archived = :archived')
->setParameter('archived', $options['archived'])
->leftJoin('p.convocation', 'c')
->andWhere("p.convocation IS NULL OR c.status = '" . Convocation::STATUS_PENDING . "'");
return $builder->getQuery()->execute();
is returning an error:
[Syntax Error] line 0, col 106: Error: Expected Literal, got 'JOIN'
This is the formed query:
SELECT p FROM ProProposalBundle:Proposal p LEFT JOIN ProProposalBundle:Proposal:Vote v LEFT JOIN ProUserBundle:User u LEFT JOIN p.convocation c WHERE v.proposal = p AND v.user = u AND (v.decision = "in_favor" OR v.decision = "against") AND u = :user AND p.community = :community AND (p.convocation IS NULL OR c.status = 'pending') ORDER BY p.created desc
LEFT JOIN is missing the ON or WITH condition. The question is: what am I doing wrong with DQL query? Am I wrong with leftJoin() method?
Doctrine ORM needs you to tell which relation is joined, not the entity itself (you did it well with p.convocation) :
$builder->select('p')
->from('ProProposalBundle:Proposal', 'p')
->leftJoin('ProProposalBundle:Proposal\Vote', 'v', 'WITH', 'v.proposal = p AND v.user = :user AND (v.decision = :in_favor OR v.decision = :against)')
->setParameter('user', $options['user'])
->setParameter('in_favor', 'in_favor')
->setParameter('against', 'against')
->andWhere('p.community = :community')
->setParameter('community', $community)
->andWhere('p.archived = :archived')
->setParameter('archived', $options['archived'])
->leftJoin('p.convocation', 'c')
->andWhere("p.convocation IS NULL OR c.status = :pending")
->setParameter('pending', Convocation::STATUS_PENDING);
return $builder->getQuery()->execute();
edit: I inversed Vote relation as you commented and removed useless WHERE clauses (Doctrine automatically resolves JOIN ON clause. I also transferred some WHERE clauses about joins in the optional params (WITH in DQL).
edit2: Without relation between Proposal and Vote, not sure it works.
edit3: Best practice is to use setParameter for all values in WHERE clauses.

Doctrine2: createQueryBuilder which has an innerJoin with more than one condition

I basically want to do this SQL statement:
SELECT * FROM Table1
JOIN Table2
ON (
Table2.ID = Table1.THIS_ID
OR
Table2.ID = Table1.THAT_ID
)
Using createQueryBuilder and NOT createQuery.
Is it possible?
All the examples I can find only deal with a single condition and don't tackle the issue of AND/OR within a join.
Thanks.
You can try something like that (in a repository for instance):
$qb = $this->createQueryBuilder('t1');
$qb->join('t1.table2', 't2', Expr\Join::WITH, 't2.id = t1.thisId OR t2.id = t1.thatId');
...
You can do it like this:
$qb->leftJoin(
'u.Phonenumbers',
'p',
Expr\Join::WITH,
$qb->expr()->orx(
$qb->expr()->eq('t.this_id', 't1.id'),
$qb->expr()->eq('t.this_id', 't1.id')
)
)

Symfony2 doctrine DQL does not replace wildcards

I'm trying to query the model from my Symfony2 project and I am not able to replace wildcards into my DQL query. Look;
$q2 =
'SELECT
p.codigo,
p.descripcion,
SUM(l.cantidad) as cantidad,
SUM(l.cantidad*l.pvp) as euros
FROM
MGFAppBundle:LineaVenta l
JOIN
MGFAppBundle:Producto p
WITH
l.producto = p.id
JOIN
l.venta v
WITH
l.venta = v.id
WHERE
l.producto IN (:array)
AND
v.farmacia = :farmacia
GROUP BY
p.codigo';
$query2 = $this->em->createQuery($q2)
->setParameter('farmacia', $farmacia)->setParameter('array', $array);
$porFarmacia = $query2->getResult();
// This does not return a single value, when it should return 2 lines.
echo $query2->getSQL();
// Returns:
// SELECT p0_.codigo AS codigo0, p0_.descripcion AS descripcion1, SUM(l1_.cantidad) AS sclr2, SUM(l1_.cantidad * l1_.pvp) AS sclr3 FROM LineaVenta l1_ INNER JOIN Producto p0_ ON (l1_.lineaventas_id = p0_.id) INNER JOIN Venta v2_ ON l1_.venta_id = v2_.id AND (l1_.venta_id = v2_.id) WHERE l1_.lineaventas_id IN (?) AND v2_.farmacia_id = ? GROUP BY p0_.codigo
So, question marks where parameters should be. Any hint? Thanks in advance.

Merging result of two queries

I'm making two queries:
Dim worker = (From p in db.workers where p.dateAdded > today
select new with{.name = p.name, .desc = p.description})
Dim client = (From p in db.clients where p.dateAdded > today
select new with{.name = p.name, .desc = p.description})
How can I merge those two queries to have only one I can use as DataSource.
Try something like this
Dim Merged = (From p in db.workers where p.dateAdded > today
select new with{.name = p.name, .desc = p.description})
.Union
(From p in db.clients where p.dateAdded > today
select new with{.name = p.name, .desc = p.description})
Use Distinct if want to get distinct result.
var merged = worker.Concat(client).Distinct();
or
var mergedList = worker.Union(client).ToList();
Can you specify what exactly you want to do?
1. Merge the results in one set - if yes, you can use huMpty duMpty's proposal
2. If you want to do something similar to DataSet with two DataTables with Linq query I'm not sure if this is achievable.
Hope this helps!
Use Union which provides your expected result.
Have look at Return the Set Union of Two Sequences (LINQ to SQL)

Resources