Showing posts with label outer join. Show all posts
Showing posts with label outer join. Show all posts

Thursday, 17 March 2022

Join in SQL

There are lots of nice diagrams explaining the difference between the different joins in SQL.

References

Code Project for those who Code - Visual Representation of SQL Joins
https://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins

Saturday, 5 September 2015

LEFT JOIN FETCH returns double results

I recently got a Bugreport from my manager that she was seeing double rows in one of our screens. After a little research I found the culprit to be the following (paraphrased) HQL query.

SELECT order from Order order LEFT JOIN FETCH order.items

The resultset returned from the database will look like this:
orderidcustomeriddateorderitemidorderidarticlenramount
112015-01-01112455
112015-01-01215741
As you can see, the order appears twice, once for each order item.

What we want to get from Hibernate is:

What we get from hibernate is:
Order
Order@25AF4E
Order@25AF4E
However, this is by design. As you can see you get two Orders, but they both refer to the same instance. Things are as it should be.

To fix this, see the great answer by Gavin King1 or on StackOverflow2.

When changing the result into:
SELECT DISTINCT order from Order order LEFT JOIN FETCH order.items
The double rows disappears, however the distinct does go through to the database (where it does nothing, as the rows are already distinct) however, it also adds the ResultTransformer implicitly, causing me to get the one row as designed.

Talked about it with the Architect, he doesn't like the use of 'distinct' in HQL queries, because:
  • it is unclear how it will be processed (locally or in the database)
  • may be a cause for performance issues if the distinct is forwarded to your database
  • In general, if you need a 'distinct' in your query to defeat double data, chances are that the query could use some improvements
With an explicit ResultTransformer, the code looks like the following:
List result = session.createQuery("select o from Order o left join fetch o.items"
                      .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
                      .list();
And the problem is fixed.

References

[1] JBoss - Hibernate FAQ
https://developer.jboss.org/wiki/HibernateFAQ-AdvancedProblems#jive_content_id_Hibernate_does_not_return_distinct_results_for_a_query_with_outer_join_fetching_enabled_for_a_collection_even_if_I_use_the_distinct_keyword
[2] StackOverflow - Hibernate Criteria returns children multiple times with FetchType.EAGER
http://stackoverflow.com/questions/1995080/hibernate-criteria-returns-children-multiple-times-with-fetchtype-eager

Wednesday, 27 February 2013

(+) to LEFT/RIGHT OUTER JOIN

Recently had to transform an Oracle SQL Query into a Standard SQL Query. One of the three steps to take was changing the Oracle notation for outer joins into a "LEFT OUTER JOIN" and "RIGHT OUTER JOIN".

(+) is an Oracle specific function[1].

Let's go with the old and trivial example of the employees and the departments in a company, before we dive any deeper. It seems to work for everyone else, so it should work here.

As we see if the (+) is on the right of the expression, it is a "LEFT OUTER JOIN" and vice versa.

The example comes straight from [3]. It will show NULL for the department values for all employees that are not assigned to a department. Wikipedia has a nice article on the behaviour of outer joins.[4]

Multiple Outer Join


This is an example of how you could use left join multiple times.
In my work, what I usually find, is a query that selects from a master table that needs to provide all records, left joined with the rest of the world, just in case the records in other tables do not exist.

This won't work


You can write conditions in the "ON" clause, however, these conditions must be related to the SLAVE table. The following, for example, will not work.[2]

It will show all employees, even the ones that are no longer working for the company.

The solution here is to move the offending condition into the WHERE clause.

Odd one out

The example below, I encountered, is a bit odd, as it is not really an outer join between tables. It is used here to prevent having to write the 'or is null' part.

References

[1] Oracle (+)
http://docs.oracle.com/cd/B28359_01/server.111/b28286/queries006.htm
[2] The ON condition
http://www.oreillynet.com/pub/a/network/2002/10/01/whatsinacondition.html>
[3] Example Oracle Left Outer Join
http://www.dba-oracle.com/tips_oracle_left_outer_join.htm
[4] Wikipedia JOIN SQL
http://en.wikipedia.org/wiki/Join_%28SQL%29
Outer joins in Oracle
https://blogs.oracle.com/optimizer/entry/outerjoins_in_oracle
A Visual Explanation of SQL Joins
http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html