Reputation: 164
I'm trying to figure out how to achieve conditional joins in doctrine.
I have an entity A
with two fields, let's call them b
(referencing a single B
object) and c
(referencing a single C
object) respectively.
/**
* @Entity
**/
class A
{
/** @ManyToOne(targetEntity="B") **/
protected $b;
/** @OneToOne(targetEntity="C") **/
protected $c;
}
I want to write a DQL query which is going to perform an INNER JOIN
on $b
ONLY if $b
is not null, and if $b
is null the INNER JOIN
should be applied to$c
instead (if $c
is not null too).
I tried combining INNER JOINS
with WITH
clauses checking for null values, but this doesn't work obviously.
SELECT a FROM model\entity\A a
INNER JOIN a.b ab WITH ab IS NOT NULL INNER JOIN ab.d abd (...)
INNER JOIN a.c ac WITH ac IS NOT NULL (...)
I also tried combining LEFT JOINS
without success.
Long story short, here's the kind of DQL I'd like to obtain :
SELECT a FROM model\entity\A a
IF a.b IS NOT NULL INNER JOIN a.b ab WITH (...)
IF a.b IS NULL INNER JOIN a.c ac WITH (...)
I'll admit I don't even know if that kind of behaviour is achievable. I think it would be easier to split this into two distinct queries, one joining on $b
and the other joining on $c
then merging the results myself, but I'd really like to find a single-query solution (provided there is any).
Thanks for reading, and for any eventual help.
Cheers!
Upvotes: 2
Views: 2479
Reputation: 164
So I couldn't find a solution while working with conditions directly in the JOIN
statements. However, I decided to join all the entities I needed, and perform the condition checks in a classic WHERE
statement.
If anyone runs into the same kind of issue, here's how I solved this :
Doesn't work :
SELECT a FROM model\entity\A a
LEFT JOIN a.b ab WITH ab IS NOT NULL INNER JOIN ab.d abd (...)
LEFT JOIN a.c ac WITH ac IS NOT NULL (...)
Works :
SELECT a FROM model\entity\A a
LEFT JOIN a.b ab
LEFT JOIN ab.d abd
LEFT JOIN a.c ac
WHERE ((ab IS NOT NULL AND (...)) OR (ac IS NOT NULL AND (...))) AND (...)
Thanks @Balmipour for telling me how to close this topic.
Upvotes: 1
Reputation: 16107
What you are describing is not possible in SQL, there is no concept of conditional joins because the structure of the result set must be consistent.
DQL only enhances SQL in the respect of ORM mapping not in the respect of adding features not present in SQL. On the contrairy DQL does not support SQL features not present in the SQL standards or which have no common ground between the major SQL RDBMS vendors -- i.e.: which are not supported by most vendors or have no equivalents in most vendors.
You can however build some PHP logic to help you with that; for example you can use the Doctrine QueryBuilder to build the query based on PHP-level if
conditions evaluated using pre-fetched PHP-level data.
For example you could run a couple of DQL queries to pre-fetch the IDs from the a.b IS NULL
group and the a.b IS NOT GROUP
(separately) and then continue with one or more queries fetching the necessary data based on those IDs.
Upvotes: 1