Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the order of conditions in a where clause relevant if both sides are left joined entities?

Tags:

sql

oracle

We have two queries on our database, where the only difference is the order of the conditions in an OR clause.

Queries of the same structure work fine on a similar data set on another database. We are working with Oracle 12.2.

The Bestand table has two connected entities where either one of them is always filled. In our example the Article is connected the KbArticle is always null. In one of our queries, we get all results for which the article id works in the other case we do not. All of the Bestand entities fulfill the two last conditions (cod_lbr = 12, flg_sperre = 0)

SELECT bestand0_.*
FROM tbl_bestand bestand0_
LEFT OUTER JOIN tbl_kb_artikel customeror1_
ON bestand0_.id_kb_artikel=customeror1_.id_kb_artikel
LEFT OUTER JOIN tbl_artikel article2_
ON bestand0_.id_artikel          =article2_.id_artikel
WHERE (customeror1_.id_kb_artikel=3017874 OR article2_.id_artikel          =3017874)
AND bestand0_.cod_lbr            =12
AND NVL(bestand0_.flg_sperre,0)  = 0;

yields results Link to Explain Plan

SELECT bestand0_.*
FROM tbl_bestand bestand0_
LEFT OUTER JOIN tbl_kb_artikel customeror1_
ON bestand0_.id_kb_artikel=customeror1_.id_kb_artikel
LEFT OUTER JOIN tbl_artikel article2_
ON bestand0_.id_artikel          =article2_.id_artikel
WHERE (article2_.id_artikel          =3017874 OR customeror1_.id_kb_artikel=3017874)
AND bestand0_.cod_lbr            =12
AND NVL(bestand0_.flg_sperre,0)  = 0;

yields no results Link to Explain Plan

What makes absolutely no sense to me, as all of the results that we should get fulfill all of the statements in the where clause is that if you leave the last two conditions, the query returns the expected results, so if we modify our query to:

SELECT bestand0_.*
FROM tbl_bestand bestand0_
LEFT OUTER JOIN tbl_kb_artikel customeror1_
ON bestand0_.id_kb_artikel=customeror1_.id_kb_artikel
LEFT OUTER JOIN tbl_artikel article2_
ON bestand0_.id_artikel          =article2_.id_artikel
WHERE (article2_.id_artikel          =3017874 OR customeror1_.id_kb_artikel=3017874);

we get results again Link to Explain Plan

I would expect both queries to yield the same results, I can not understand why the order of the conditions should affect the outcome of the query in any way. Do we have some indices messed up here? It must be database specific as our queries work fine on another database, same version, with a similar set of data.

** UPDATE **

Unfortunately the query with the AND OTHER_ID IS NULL as @kfinity had the same problem as the queries above which makes absolutely no sense to me. After we disabled the Adaptive Statistics Optimizer that @Kuvick mentioned our queries both returned results again with the following explain plans:

Explain plan Query 1 Explain plan Query 2

So turning that optimizer off solved our problems.

like image 277
peach Avatar asked Jan 30 '19 13:01

peach


People also ask

Can we use WHERE clause in left outer join?

In the WHERE clause, you can specify left and right outer joins only. To outer join tables TABLE1 and TABLE2 and return non-matching rows from TABLE1 (a left outer join), specify TABLE1 LEFT OUTER JOIN TABLE2 in the FROM clause or apply the (+) operator to all joining columns from TABLE2 in the WHERE clause.

WHERE clause before join or after join?

Normally, filtering is processed in the WHERE clause once the two tables have already been joined. It's possible, though that you might want to filter one or both of the tables before joining them. For example, you only want to create matches between the tables under certain circumstances.

What is the difference between WHERE and join on clause?

Is there a difference between the WHERE and ON clause? Yes. ON should be used to define the join condition and WHERE should be used to filter the data.

Does WHERE come before inner join?

The where clause will be executed before the join so that it doesn't join unnecessary records.


1 Answers

We identified the problem to be the Oracle setting OPTIMIZER_ADAPTIVE_PLANS and OPTIMIZER_ADAPTIVE_STATISTICS. By default after setting up the DB the first one is active and the second one is deactivated.

In our case both were activated. Right after deactivating OPTIMIZER_ADAPTIVE_STATISTICS (i.e. going back to the default settings) both queries returned the same results (as one would expect). These settings can be checked with the follwing query:

SELECT * FROM v$parameter WHERE 1 = 1 AND LOWER(name) LIKE LOWER('optimizer_ad%') ORDER BY 1 DESC;
like image 79
Kuvick Avatar answered Nov 15 '22 12:11

Kuvick