'How to use left join like right join in Doctrine

So I've been racking my brain for a while now. In Doctrine there is no concept of right join. I know that you can use a left join like a right join but I can't figure it out for my example which is why I'm here.

My example: I have an entity in Doctrine which has a one-to-one relationship with itself called "parent". I am trying to get all entities and their children(if they exist) with no duplicates.

With a right join this is simple because I can say:

    SELECT parent.*, child.*
    FROM table child
    RIGHT JOIN table parent ON parent.id = child.parent_id
    WHERE parent.parent_id is null;

But using a left join I am returned results that I can not figure out what the where clause should be to filter them out.

So my question is "Does doctrine have a way of doing right join" or "How can I use the left join operation like a right join"?

---EDIT---

You guys are correct in what you are saying about changing the ordering of tables I select from but I am using Doctrine so the relationship does child->parent. Here is my doctrine query:

My Entity:

/**
 * @Entity
 * @Table(name="entity")
 */
class Entity
{
...
/**
 * @OneToOne(
 *     targetEntity="Entity",
 *     fetch="EAGER"
 * )
 * @JoinColumn(name="parent_id", referencedColumnName="id")
 */
private $parent;
...
}

My doctrine select statement:

$em->createQueryBuilder()
->select(array('child', 'parent'))
->from('Entity', 'child')
->leftjoin('child.parent', 'parent')
->orderBy('parent.id','asc')
->getQuery()
->execute();

I am not sure how and IF I can switch the ordering of tables. I also tried creating another relationship from entity to itself (like the way I did parent) but called it child. But when I updated the db with the new schema doctrine threw errors.

Any ideas? And Thanks for the quick responses!

---EDIT 2---

Left join sql and results:

SELECT child.id, child.changed_timestamp, child.parent_entity_id, parent.id,
  parent.changed_timestamp, parent.parent_entity_id 
FROM content child 
LEFT JOIN content parent ON child.parent_entity_id = parent.id   
ORDER BY parent.id ASC

child_id    child_timestamp parent_entity_id    parent_id   parent_timestamp    parent_entity_id
1           8/16/12 20:29   NULL                NULL        NULL                NULL
7           9/20/12 16:07   NULL                NULL        NULL                NULL
8           8/17/12 16:08   NULL                NULL        NULL                NULL
9           8/17/12 20:44   NULL                NULL        NULL                NULL
10          8/17/12 21:03   NULL                NULL        NULL                NULL
11          8/17/12 21:17   NULL                NULL        NULL                NULL
194         9/19/12 9:58    NULL                NULL        NULL                NULL
195         9/20/12 10:38   NULL                NULL        NULL                NULL
196         9/19/12 11:58   NULL                NULL        NULL                NULL
197         NULL            196                 196         9/19/12 11:58       NULL
200         9/20/12 16:02   1                   1           8/16/12 20:29       NULL
202         9/20/12 16:35   NULL                NULL        NULL                NULL
204         9/21/12 8:41    NULL                NULL        NULL                NULL
206         NULL            204                 204         9/21/12 8:41        NULL

Right join results:

SELECT child.id, child.changed_timestamp, child.parent_entity_id, parent.id, 
 parent.changed_timestamp, parent.parent_entity_id 
FROM content child 
RIGHT JOIN content parent ON child.parent_entity_id = parent.id   
WHERE parent.parent_entity_id is null
ORDER BY parent.id ASC

child_id    child_timestamp parent_entity_id    parent_id   parent_timestamp    parent_entity_id
200         9/20/12 16:02   1                   1           8/16/12 20:29       NULL
NULL        NULL            NULL                7           9/20/12 16:07       NULL
NULL        NULL            NULL                8           8/17/12 16:08       NULL
NULL        NULL            NULL                9           8/17/12 20:44       NULL
NULL        NULL            NULL                10          8/17/12 21:03       NULL
NULL        NULL            NULL                11          8/17/12 21:17       NULL
NULL        NULL            NULL                194         9/19/12 9:58        NULL
NULL        NULL            NULL                195         9/20/12 10:38       NULL
197         NULL            196                 196         9/19/12 11:58       NULL
NULL        NULL            NULL                202         9/20/12 16:35       NULL
206         NULL            204                 204         9/21/12 8:41        NULL

I want to achieve the results with the right join sql. Unique parent entities with their associated children(if they exists) but I need to achieve it using doctrine. Thanks again!



Solution 1:[1]

@491243's comment is correct: if you were using sql this would be a trivial problem because left and right joins are easily convertible and relational predicates can be expressed in any order.

The real problem appears not to be how to rewrite a right join as a left one but how to traverse your relationship in the other direction. Presumably you can't just do something like this?:

$em->createQueryBuilder()
->select(array('child', 'parent'))
->from('Entity', 'parent')
->leftjoin('parent.child', 'child')
->orderBy('parent.id','asc')
->getQuery()
->execute();

Solution 2:[2]

try this one:

SELECT
    parenttable.*, childtable.*
FROM childtable
RIGHT JOIN parenttable ON parenttable.id = childtable.parent_id
WHERE
    parenttable.parent_id IS NULL
    AND
    childtable.childid IS NOT NULL;

Solution 3:[3]

the left join you posted did not have: WHERE parent.parent_entity_id is null

i am going to guess that within your data, this means the record is itself not a child.

so if you just need the right join sql you provided as a left join, here you go:

SELECT child.id, child.changed_timestamp, child.parent_entity_id, parent.id, parent.changed_timestamp, parent.parent_entity_id FROM content parent LEFT JOIN content child ON child.parent_entity_id = parent.id
WHERE parent.parent_entity_id is null ORDER BY parent.id ASC

NOTE: if your data allows for multiple generations, e.g. grand-children etc., the where clause above is filtering out not only children, but also grand-children. This has implications on the child data returned: children will not be returned if they are grand-children.

Solution 4:[4]

Not really familiar with Doctrine script, but... This old-style JOIN should achieve the same result as a RIGHT JOIN in most SQL scripts:

    SELECT parent.*, child.*
    FROM table child, table parent 
    WHERE parent.id = child.parent_id
    OR child.parent_id IS NULL;

Solution 5:[5]

These two statements are equivalent:

SELECT parent.*, child.*
FROM table child
RIGHT JOIN table parent ON parent.id = child.parent_id
WHERE parent.parent_id is null;

SELECT parent.*, child.*
FROM table parent 
LEFT JOIN table child ON child.parent_id = parent.id 
WHERE parent.parent_id is null;

I never use RIGHT JOIN. I think it is only included in SQL for completeness.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Rory
Solution 2 MaGnetas
Solution 3 spioter
Solution 4 Phrancis
Solution 5 Jonathan Roberts