I'm new to SQL. I need help with left join with an select.
The part I'm interested in:
Select...
from table t1
left join table t2
on t1.id=t2.id,
left join (select * from table 3 where ...) t3
on t1.id=t3.id
where t1.id='something'
Also i tried to moved in the where clause the t1.id(+)=t3.id but didn't work.
I think the logic you want is:
Select...
from t1 left join
t2
on t1.id = t2.id left join
t3
on t1.id = t3.id and
<t3 conditions go here>
where t1.id = 'something'
You have a superfluous comma -- and commas should never be in the FROM clause.
You also have a superfluous subquery. You can get the same functionality by just including the condition in the ON clause.
Related
I am currently trying to join a few tables together (maybe join 2 additional more if possible) but with how my query is written right now, I cant even see the results with 3 tables
select t1.x,
t1.y,
t1.z,
t4.a,
t4.b,
t4.c,
t4.d
from t1
left join t2 on t1.id=t2.id
left join t3 on t2.id=t3.id
left join t4 on t1.id2=t4.id
where t1.date between 'x' and'x'
and t1.city not in ('x')
and t3.column = x;
Is there a way to optimize this code to run faster and perhaps make it able to add more tables to it?
Thank you in advance!
Your query has some logic issues that might help with the speed.
t2 is joined to t1 when they have the same id value.
t3 is then pulled in, if and only if, there was a row in t2 and it has the same value as t1 and t2.
Finally, in your where clause, the t3.column has to be x else it's filtered.
This means a row in t3 has to exist. Every t1 record that doesn't have a t2 record and a t3 record will be filtered out with that where. Thus you don't need a left join, you need an INNER join.
select t1.x,
t1.y,
t1.z,
t4.a,
t4.b,
t4.c,
t4.d
from t1
inner join t2 on t1.id=t2.id
inner join t3 on t2.id=t3.id
left join t4 on t1.id2=t4.id
where t1.date between 'x' and'x'
and t1.city not in ('x')
and t3.column = x;
In some DBMS you can move the t3.column clause to the join command which can help filter out the rows earlier in the plan.
select t1.x,
t1.y,
t1.z,
t4.a,
t4.b,
t4.c,
t4.d
from t1
inner join t2 on t1.id=t2.id
inner join t3 on t2.id=t3.id and t3.column = x
left join t4 on t1.id2=t4.id
where t1.date between 'x' and'x'
and t1.city not in ('x');
My final advise is to take a close look at t2 to see if you really need it. Ask yourself, is there a reason a row has to exist in t2 in order for me to get the right results? ... because if t1.id = t2.id then t1.id = t3.id and you can eliminate the t2 table completely.
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)
bit of a novice question, I am running a query and left joining and wanted to know whether there was a difference when you specify a filter in terms of performance, in e.g below, top I filter straight after first join and below I do all joins and then filter:
Select t1.*,t2.* from t1 t1
left join t2 t2
on t1.key = t2.key
and t1.date < today
left join t3 t3
on t2.key2 = t3.key
vs
Select t1.*,t2.* from t1 t1
left join t2 t2
on t1.key = t2.key
left join t3 t3
on t2.key2 = t3.key
and t1.date < today
Learn what LEFT JOIN ON returns: INNER JOIN ON rows UNION ALL unmatched left table rows extended by NULLs. Always know what INNER JOIN you want as part of an OUTER JOIN.
In general your queries have different inner join & null-extended rows for the 1st left joins & then further differences due to more joining. Unless certain constraints hold, the 2 queries return different functions of their inputs. So comparing their performance seems moot.
This is somewhat of a followon to SQL JOIN where to place the WHERE condition?
I would prefer to use the USING clause on the join, but am not yet able to put the field value condition with the join.
SELECT 1
FROM table1 t1
JOIN table2 t2 USING(id) AND t2.field = 0;
ORA-00933: SQL command not properly ended
Is it possible to have USING and another condition as part of the JOIN clause?
You can use:
SELECT 1
FROM table1 t1
JOIN table2 t2 USING(id)
WHERE t2.field = 0;
Using USING(id) is like using ON t1.id = t2.id except that in the JOIN result instead of two columns t1.id & t2.id there is only one id column.
For INNER JOIN USING with a condition followed by an OUTER JOIN you need a subquery to keep the WHERE with the USING:
SELECT ...
FROM (SELECT id, ...
FROM table1 t1
JOIN table2 t2 USING(id)
WHERE t2.field = 0) s
LEFT JOIN ...;
For an OUTER JOIN USING with a condition you need a subselect:
SELECT ...
FROM table1 t1
LEFT JOIN (SELECT *
FROM table2 t2
WHERE t2.field = 0) t2
USING (id);
See this re ON/WHERE with JOIN. See this re ON/WHERE when mixing INNER & OUTER JOINs.
I have three tables and two seperate SQL queries which are working correctly and I am having correct results.
If I try to join these three tables I am having null as result.
First query:
select T1.ID,T3.COMPANY
from T1,T3
where (T1.status!='CLOSED') and (T1.PRIORITY)>5 and T1.CLASSID=T3.CLASSID
Second query:
SELECT T1.ID, T2.DESCRIPTION
FROM T1
LEFT OUTER JOIN T2
ON T1.ID=T2.KEY
WHERE T1.status!='CLOSED'
AND (T2.CREATEDATE= (SELECT MAX(CREATEDATE)
FROM T2
WHERE T2.KEY=T1.ID))
I tried to join them but as result I am having null:
select T1.ID,T3.COMPANY,T2.DESCRIPTION
from T1
INNER JOIN T3 ON T1.CLASSID=T3.CLASSID
LEFT OUTER JOIN T2
ON T1.ID=T2.KEY
where (T1.status!='CLOSED') AND (T1.PRIORITY)>5
AND (T2.CREATEDATE= (SELECT MAX(CREATEDATE)
FROM T2
WHERE T2.KEY=T1.ID))
like it does not recognized last part for taking MAX value from T2 table.
What am I doing wrong? Thanks for help
Firstly, use an alias for the subquery on table T2.
T2.CREATEDATE =
(SELECT MAX(T2Alias.CREATEDATE)
FROM T2 AS T2Alias
WHERE T2Alias.KEY = T1.ID)
Secondly, consider moving this condition into the ON clause of the LEFT JOIN to table T2.
The first thing that jumps out at me is the new dependency on both T1.Priority > 5 and T2.CreateDate value being equal to the result of the inline query:
( AND (T1.PRIORITY) > 5
AND (T2.CREATEDATE =
(SELECT MAX(CREATEDATE) FROM T2 WHERE T2.KEY = T1.ID) )
Without the data it's difficult to check however this may be the issue