Combining multiple tables with uncommon columns - sql

How can i get my expected output. I join first two tables by Left Outer Join, but as soon as i join the third one my expected result goes away.

You want left joins:
select
t1.*,
t2.runno,
t3.blockno,
t4.quantity
from t1
left join t2
on t2.ordercode = t1.ordercode and t2.orderitem = t1.orderitem
left join t3
on t3.runno = t2.runno
left join t4
on t4.blockno = t3.blockno

Related

When to use right join or full outer join

I work with DB / SQL almost on a daily basis and the more I work with sql, the more I'm the opinion that there is no reason to use a right join or a full outer join.
Let's assume we have two tables: table1 and table2. Either I want to receive additional information for the rows in table1 so I can use an inner join on table2 and if I want to keep the original rows if there is no match, I use the left join then:
In case I have to add additional information to table 2, I can do the same and left join table 2 to table on. So I do not see a reason why I should ever use a right join. Is there any use case where you can not use a left join for a right join?
I also wondered if I would ever need a full outer join. Why would you join two tables and keep the rows that do not match of BOTH tables? We you could also achieve this by using two left joins.
Why would you join two tables and keep the rows that do not match of BOTH tables?
The full join has cases where it is useful.One of them is comparing two tables for differences like XOR between tables:
SELECT *
FROM t1
FULL JOIN t2
ON t1.id = t2.id
WHERE t1.id IS NULL
OR t2.id IS NULL;
Example:
t1.id ... t2.id
1 NULL
NULL 2
you could also achieve this by using two left joins.
Yes you could:
SELECT t1.*, t2.*
FROM t1
LEFT JOIN t2
ON t1.id = t2.id
WHERE t2.id IS NULL
UNION ALL
SELECT t1.*, t2.*
FROM t2
LEFT JOIN t1
ON t1.id = t2.id
WHERE t1.id IS NULL;
Some SQL dialects does not support FULL OUTER JOIN and we emulate it that way.
Related: How to do a FULL OUTER JOIN in MySQL?
On the other hand RIGHT JOIN is useful when you have to join more than 2 tables:
SELECT *
FROM t1
JOIN t2
...
RIGHT JOIN t3
...
Of course you could argue that you could rewrite it to correspodning form either by changing join order or using subqueries(inline views). From developer perspective it is always good to have tools(even if you don't have to use them)

order of a JOIN

This is a very simple question but i couldn't get the result for the life of me.
Where is the "leftness" or "rightness" of a table determined in SQL?
so if have to tables, t1 and t2 with this query:
SELECT * FROM t1 LEFT JOIN t2 ON t1.id = t2.id
I'm certain t1 is on the left but what if i change the order of the ON statement like so:
SELECT * FROM t1 LEFT JOIN t2 ON t2.id = t1.id
is t2 now on the left or is t1 still on the left because it is on the left of LEFT?
i appreciate the time anyone takes to answer this simple question.
n.b. my question is not about the difference between LEFT and RIGHT joins
The order of a table name matters in Join (LEFT, RIGHT), Not the order of join condition.
So here, your both queries are same.
Left join or Left outer join requires table name with the condition "t1 LEFT JOIN t2". Here, t1 is left joined with t2 meaning all elements of t1 and matching rows on t2.
The LEFT JOIN keyword returns all records from the left table (table1), and the matched records from the right table (table2). The result is NULL from the right side, if there is no match.
Similarly
The RIGHT JOIN keyword returns all records from the right table (table2), and the matched records from the left table (table1). The result is NULL from the left side, when there is no match.
Putting in your terms the LEFTness or RIGHTness of a table is determined at
FROM table1 LEFT/RIGHT JOIN table2.
Whatever table is before the keyword LEFT join is considered Left table and similarly whatever table is after keyword RIGHT join is considered as Right table. For more info you can refer SQL-Joins

Join table order

Query1: t1 left join t2 on some condition cross join t3 right join t4 on some condition
Query2: t1 left join t2 on some condition cross join t4 left join t3 on some condition
Will the result of these queries be the same or not?
They are not the same.
Ex. if we consider all the tables have the same number of rows, the first query returns less rows than the second one.

Stuck on multiple Left Join and Inner Join

I've to make a query on Oracle and i'm a little bit stuck with it. In my TABLE1, I've 287 reccords so I want all informations from TABLE2 AND TABLE3 that egal with my 287 reccords (that's why I use Left Join). But I also want all reccords that match between TABLE2 and TABLE4, TABLE4 AND TABLE5 (That's why I use Inner Join).
But my query don't work and I don't know why. Someone can help me ?
My query :
SELECT distinct(TABLE1.NUM_SIN),
TABLE1.LIBELLE,
TABLE1.DATE_FRAIS,
TABLE2.CODE_SIN,
TABLE2.PKPR,
TABLE1.MT,
TABLE4.POSTBUD,
TABLE3.VEENG
FROM TABLE1
LEFT JOIN TABLE2
ON TABLE2.NUM_SIN = TABLE1 .NUM_SIN
INNER JOIN TABLE4
ON TABLE4.NUM_SIN = TABLE2.NUM_SIN
AND TABLE4.SCSO = TABLE2.SCSO
LEFT JOIN TABLE5
ON TABLE5.CDC = TABLE4.NO
AND TABLE5.CDEXE = TABLE4.CDEXE
AND TABLE5.SCSO = TABLE4.SCSO
LEFT JOIN TABLE3
ON TABLE3.CNCT = TABLE1.NUM_SIN
WHERE ... ;
A graph to understand :
Thx in advice !
I think the issue here is perhaps that you really don't want to use an inner join in your query, and perhaps that you don't know exactly what the difference is between an inner join and an outer join.
The inner join in your query will return ONLY the rows from TABLE4 that are a match in TABLE2. Joins are sequential and cumulative, so your remaining LEFT joins will have the reduced rowset on the left side of the join.
Thus, I believe you will want to use LEFT joins throughout your query, e.g.:
SELECT distinct(TABLE1.NUM_SIN),
TABLE1.LIBELLE,
TABLE1.DATE_FRAIS,
TABLE2.CODE_SIN,
TABLE2.PKPR,
TABLE1.MT,
TABLE4.POSTBUD,
TABLE3.VEENG
FROM TABLE1
LEFT JOIN TABLE2
ON TABLE2.NUM_SIN = TABLE1 .NUM_SIN
LEFT JOIN TABLE4
ON TABLE4.NUM_SIN = TABLE2.NUM_SIN
AND TABLE4.SCSO = TABLE2.SCSO
LEFT JOIN TABLE5
ON TABLE5.CDC = TABLE4.NO
AND TABLE5.CDEXE = TABLE4.CDEXE
AND TABLE5.SCSO = TABLE4.SCSO
LEFT JOIN TABLE3
ON TABLE3.CNCT = TABLE1.NUM_SIN
WHERE ... ;
Are you sure you don't want to left join to table4? The way it is written only values in TABLE4 would be allowed which would limit the results from table2 and table5.
NB - the image CDN is filtered here so I can't see the image.
SELECT --
FROM TABLE1
LEFT JOIN TABLE2 ON TABLE2.NUM_SIN = TABLE1 .NUM_SIN
LEFT JOIN TABLE3 ON TABLE3.CNCT = TABLE1.NUM_SIN
-- unless you want to reduce the number of table2 rows use left join here.
LEFT JOIN TABLE4 ON TABLE4.NUM_SIN = TABLE2.NUM_SIN AND TABLE4.SCSO = TABLE2.SCSO
LEFT JOIN TABLE5 ON TABLE5.CDC = TABLE4.NO
AND TABLE5.CDEXE = TABLE4.CDEXE
AND TABLE5.SCSO = TABLE4.SCSO
WHERE ... ;

Rewrite left outer join involving multiple tables from Informix to Oracle

How do I write an Oracle query which is equivalent to the following Informix query?
select tab1.a,tab2.b,tab3.c,tab4.d
from table1 tab1,
table2 tab2 OUTER (table3 tab3,table4 tab4,table5 tab5)
where tab3.xya = tab4.xya
AND tab4.ss = tab1.ss
AND tab3.dd = tab5.dd
AND tab1.fg = tab2.fg
AND tab4.kk = tab5.kk
AND tab3.desc = "XYZ"
I tried:
select tab1.a,tab2.b,tab3.c,tab4.d
from table1 tab1,
table2 tab2 LEFT OUTER JOIN (table3 tab3,table4 tab4,table5 tab5)
where tab3.xya = tab4.xya
AND tab4.ss = tab1.ss
AND tab3.dd = tab5.dd
AND tab1.fg = tab2.fg
AND tab4.kk = tab5.kk
AND tab3.desc = "XYZ"
What is the correct syntax?
Write one table per join, like this:
select tab1.a,tab2.b,tab3.c,tab4.d
from
table1 tab1
inner join table2 tab2 on tab2.fg = tab1.fg
left join table3 tab3 on tab3.xxx = tab1.xxx and tab3.desc = "XYZ"
left join table4 tab4 on tab4.xya = tab3.xya and tab4.ss = tab3.ss
left join table5 tab5 on tab5.dd = tab3.dd and tab5.kk = tab4.kk
Note that while my query contains actual left join, your query apparently doesn't.
Since the conditions are in the where, your query should behave like inner joins. (Although I admit I don't know Informix, so maybe I'm wrong there).
The specfific Informix extension used in the question works a bit differently with regards to left joins. Apart from the exact syntax of the join itself, this is mainly in the fact that in Informix, you can specify a list of outer joined tables. These will be left outer joined, and the join conditions can be put in the where clause. Note that this is a specific extension to SQL. Informix also supports 'normal' left joins, but you can't combine the two in one query, it seems.
In Oracle this extension doesn't exist, and you can't put outer join conditions in the where clause, since the conditions will be executed regardless.
So look what happens when you move conditions to the where clause:
select tab1.a,tab2.b,tab3.c,tab4.d
from
table1 tab1
inner join table2 tab2 on tab2.fg = tab1.fg
left join table3 tab3 on tab3.xxx = tab1.xxx
left join table4 tab4 on tab4.xya = tab3.xya
left join table5 tab5 on tab5.dd = tab3.dd and tab5.kk = tab4.kk
where
tab3.desc = "XYZ" and
tab4.ss = tab3.ss
Now, only rows will be returned for which those two conditions are true. They cannot be true when no row is found, so if there is no matching row in table3 and/or table4, or if ss is null in either of the two, one of these conditions is going to return false, and no row is returned. This effectively changed your outer join to an inner join, and as such changes the behavior significantly.
PS: left join and left outer join are the same. It means that you optionally join the second table to the first (the left one). Rows are returned if there is only data in the 'left' part of the join. In Oracle you can also right [outer] join to make not the left, but the right table the leading table. And there is and even full [outer] join to return a row if there is data in either table.
I'm guessing that you want something like
SELECT tab1.a, tab2.b, tab3.c, tab4.d
FROM table1 tab1
JOIN table2 tab2 ON (tab1.fg = tab2.fg)
LEFT OUTER JOIN table4 tab4 ON (tab1.ss = tab4.ss)
LEFT OUTER JOIN table3 tab3 ON (tab4.xya = tab3.xya and tab3.desc = 'XYZ')
LEFT OUTER JOIN table5 tab5 on (tab4.kk = tab5.kk AND
tab3.dd = tab5.dd)