How can i have INNER and LEFT JOIN in the same query? - sql

I am trying to do an INNER JOIN and LEFT JOIN in the same query in MS ACCESS and here is my query
SELECT T2.Col1, T2.Col2, T2.Col3, TB.Col1
FROM (T2
INNER JOIN TB ON
TB.Col1 = T2.Col1 AND TB.Col2 = T2.Col2)
LEFT JOIN T1
ON (T1.Col1 = TB.Col1) AND (T1.Col2 = T2.Col2)
WHERE T1.Col1 IS NULL OR T1.Col2 IS NULL
But at (T1.Col1 = TB.Col1)` it says JOIN Expression not supported. Can some one help me with this.
I don't want to create an inner query and then create another left query with that seperately

An earlier answer, since deleted, recommended you remove all the parentheses from your query. However Access requires parentheses in the FROM clause when it includes more than one join.
Since the problem is with the joins, start with a simpler query which focuses on them only. See whether this query runs without error.
SELECT *
FROM
(T2
INNER JOIN TB
ON T2.Col1 = TB.Col1 AND T2.Col2 = TB.Col2)
LEFT JOIN T1
ON T2.Col1 = T1.Col1 AND T2.Col2 = T1.Col2
Once you get the joins correct, replace * with your field names and add your WHERE clause.

Related

How to convert old Oracle (+) with multi joins [duplicate]

This question already has answers here:
Oracle "(+)" Operator
(4 answers)
Oracle join operator
(1 answer)
Oracle-Conveting SQL to ANSI SQL
(1 answer)
Conversion of Oracle join to Ansi join
(1 answer)
Closed 5 years ago.
I have Oracle sql code that uses the old and not recommended (+) notation. I have a basic understanding of how to convert but am struggling with multiple tables.
For exmaple
select [list of columns]
from table1 t1,
table2 t2,
table3 t3,
table4 t4,
table5 t5
where t2.col1 = t1.col1
and t2.col2 = t3.col2
and t4.col1(+) = t2.col3
and t5.col1(+) = t2.col4
and t5.col2(+) = t2.col5
Hope this makes sense. I believe this is slightly different from other similar questions as they did not cover multiple joins in the same query
t4.col1(+) = t2.col3
would convert to
RIGHT OUTER JOIN table2 t2 on t4.col1 = t2.col3
etc.
but since table2 should be joined to table1 first, it would be cleaner to use the more common LEFT join and flip the tables:
from table1 t1,
INNER JOIN table2 t2 ON t2.col1 = t1.col1
LEFT JOIN table3 t3 ON t2.col2 = t3.col2
LEFT JOIN table4 t4 ON t2.col3 = t4.col1
LEFT JOIN table5 t5 ON t2.col4 = t5.col1
and t2.col5 = t5.col2
Just move each join condition from the WHERE clause into the corresponding JOIN:
select [list of columns]
from table1 t1
join table2 t2
on t2.col1 = t1.col1
join table3 t3
on t3.col2 = t2.col2
left join table4 t4
on t4.col1 = t2.col3
left join table5 t5
on t5.col1 = t2.col4
and t5.col2 = t2.col5
I never use the optional (i.e. redundant) inner and outer keywords, or right join (since you can always just reverse it to make a normal left join and avoid a lot of confusion).

Exactly when to user inner join or an alternative query

SELECT .... FROM TABLE1 T1, TABLE2 T2, TABLE3 T3
WHERE T1.NAME = 'ABC' AND T1.ID = T2.COL_ID AND T2.COL1 = T3.COL2
vs
SELECT .... FROM TABLE1 T1
WHERE T1.NAME = 'ABC'
INNER JOIN TABLE2 T2 ON T1.ID = T2.COL_ID
INNER JOIN TABLE3 T3 ON T2.COL1 = T3.COL2
Two questions
In terms of performance, which will perform better and why?
If Option 2 has the better performance, when should be using Option 1? (vice versa question if Option 1 has better performance)
The second query is not correct. It should be:
SELECT .... FROM TABLE1 T1
INNER JOIN TABLE2 T2 ON T1.ID = T2.COL_ID
INNER JOIN TABLE3 T3 ON T2.COL1 = T3.COL2
WHERE T1.NAME = 'ABC'
This is the right way to write your join condition. The 1st one is accepted, but technically creates a cartesian product. All modern database deals perfectly with both 1st and 2nd queries and interprets them the same way, therefore, performance should be the same. But still, you should use the second one because it is more readable and allows you to have only one way to write join weither it is a inner, left or full outer.
The answer is easy: Don't use comma-separated joins (first query). We used these in the 1980s for the lack of something better, but then in 1992 the new syntax (second query) was introduced1, because the old syntax was error-prone (it was easier to forget to apply join criteria) and harder to maintain (was missing join criteria intended or not in a query?) and there was no standard syntax for outer joins.
1 Oracle was a little late though featuring the new syntax. They introduced the new ANSI joins in Oracle 9i in 2001.
In terms of performance: There should be no difference in speed, because DBMS optimizers see that this is essentially the same query.
Your second query is syntactically incorrect by the way. The query's WHERE clause belongs after the complete FROM clause, i.e. after all the joins:
SELECT ....
FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.col_id
INNER JOIN table3 t3 ON t2.col1 = t3.col2
WHERE t1.name = 'ABC';

Convert OUTER APPLY to LEFT JOIN

We have query which is slow in production(for some internal reason),
SELECT T2.Date
FROM Table1 T1
OUTER APPLY
(
SELECT TOP 1 T2.[DATE]
FROM Table2 T2
WHERE T1.Col1 = T2.Col1
AND T1.Col2 = T2.Col2
ORDER BY T2.[Date] DESC
) T2
But when I convert to LEFT JOIN it become fast,
SELECT Max(T2.[Date])
FROM Table1 T1
LEFT JOIN Table2 T2
ON T1.Col1 = T2.Col1
AND T1.Col2 = T2.Col2
GROUP BY T1.Col1, T1.Col2
Can we say that both queries are equal? If not then how to convert it properly.
The queries are not exactly the same. It is important to understand the differences.
If t1.col1/t1.col2 are duplicated, then the first query returns a separate row for each duplication. The second combines them into a single row.
If either t1.col1 or t1.col2 are NULL, then the first query will return NULL for the maximum date. The second will return a row and the appropriate maximum.
That said, the two queries should have similar performance, particularly if you have an index on table2(col1, col2, date). I should note that under some circumstances the apply method is faster than joins, so relative performance depends on circumstances.

Explanation about nested loop

Nested Loop Join
In this kind of join operation it process each row from outer input and loop through all rows of inner input to search for matching row based on join column.
Nested loops joins perform a search on the inner table for each row of the outer table, typically using an index.
example:
Select T1.Col2
From Table1 T1
Inner Join Table2 T2 ON T1.Col1 = T2.Col1 AND T1.Col1 between 1 AND 36
can you please explain which is outer input and inner input. Here we have two condition that is T1.Col1 = T2.Col1 AND T1.Col1 between 1 AND 36 table is first filtered by which condition
I would rather write the query in this way:
SELECT T1.Col2
FROM Table1 T1
INNER JOIN Table2 T2 ON T1.Col1 = T2.Col1
WHERE T1.Col1 BETWEEN 1 AND 36
The second condition is not a join condition, but a where condition (Table2 is not involved in solving that condition).
The optimizer of your database should be able to decide if filtering first Table1 is faster than join Table2 and then filter, I imagine that the later can be true if Table2 is quite small. Also indexes can change the query plan.
Anyway if you want to be sure about how your database is executing your query just check the query plan.
SELECT T1.Col2
FROM Table1 T1
INNER JOIN Table2 T2 ON T1.Col1 = T2.Col1
WHERE T1.Col1 >=1 and T1.Col1<36
you'll find better explaination to join follow the link
http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html

SQL Server - query with multiple joins dependent of first or second join

I have a query with 4 tables. It needs to return the value from the fourth table by joining the first table to either the second or the third table depending on if the join is on the second returned a match.
Here's what I tried after looking this up online:
SELECT t1.field1, t4.field1
FROM t1
LEFT JOIN t2 ON t1.field1 = t2.field1
LEFT JOIN t3 ON t1.field1 = t3.field1
LEFT JOIN t4 ON COALESCE(t2.field1, t3.field1)
Right now, it only returns a value from the fourth table when a match is made from the join between t1 and t2.
Is there anyway to achieve this?
Thanks in advance for your suggestions
Well, apart from what I think was an error on the copye/paste (it's missing part of the last join condition), your query should work:
SELECT t1.field1, t4.field1
FROM t1
LEFT JOIN t2
ON t1.field1 = t2.field1
LEFT JOIN t3
ON t1.field1 = t3.field1
LEFT JOIN t4
ON COALESCE(t2.field1, t3.field1) = t4.field1
Seems like your query should work as is (aside from missing expression as Lamak mentioned), alternatively:
SELECT sub.field1, t4.field1
FROM (SELECT t1.field1, COALESCE(t2.field1, t3.field1) as field2
FROM t1
LEFT JOIN t2
ON t1.field1 = t2.field1
LEFT JOIN t3
ON t1.field1 = t3.field1
)sub
LEFT JOIN t4
ON sub.field2 = t4.field1