SQL issue: JOIN on empty table - sql

For example we have the following SQL query
select T1.name
from table1 T1
join table2 T2 ON T1.id = T2.id
I have made join table2 only if it is NOT empty. If table2 is empty I don't make join
select T1.name
from table1 T1
Can I solve it by one SQL query?
It would be good to use only SQL standard.

Related

Seeking suggestion about Left join

I have two tables t1 & t2. In t1, there are 1641787 records. In t2, there are 33176007 records. I want to take two columns from table2 and keep everything of t1. When I use left join with t1 to t2, I got more records than t1. I would like to get a similar number of records as t1 after joining. Please give me a suggestion. Here is my code:
SELECT t1.*,
t2.City
FROM t1
LEFT JOIN
t2
ON t1.ID = t2.ID;
You can aggregate and choose an arbitrary value:
select t1.*, t2.city
from t1 left join
(select t2.id, any_value(t2.city) as city
from t2
group by t2.id
) t2
on t1.id = t2.id;

How to join these tables safely?

I have a table Table1. My application code reads from Table1 like this:
Select id, table2_id, table3_id from Table1
I would like it to also return values name from tables Table2 and Table3 by changing my query like this:
select t1.id, t1.table2_id, t1.table3_id, t2.name, t3.name
from table1 t1
left outer join table2 t2 on t1.table2_id = t2.id
left outer join table3 t3 on t1.table3_id = t3.id
However, I don't want to change the behavior of the original query, which returns 1 result per row in Table1.
I believe my changes to the query are safe because they t2.id and t3.id are unique columns, so Table2 and Table3 will contain at most 1 record for each Table3 record. If I was to user inner join, this changes would not be safe, because my query would return no results if Table2 or Table3 happen to not contain the expected record.
For this scenario, are my changes safe and correct? Or is it necessary to write some subqueries to join on?
Your query looks safe:
select t1.id, t1.table2_id, t1.table3_id, t2.name, t3.name
from table1 t1 left join
table2 t2
on t1.table2_id = t2.id left join
table3 t3
on t1.table3_id = t3.id;
You can also phrase this using correlated subqueries (or a lateral join):
select t1.*,
(select t2.name from table2 t2 where t1.table2_id = t2.id) as t2_name,
(select t2.name from table3 t3 where t1.table2_id = t3.id) as t3_name,
from table1 t1;
This is even more of a guarantee that there are no duplicates. If there were, the query would return an error.

Get values from one table that are not in another

The first query works to get a value from t1 that is not in t2.
select t1.*
from table1 t1
where t1.id = '1'
and t1.id2 not in (select t2.id2 from table2 t2 where t2.id='1')
But how do how can I do the same thing using this format instead of an inner select?
select t1.*
from table1 t1, table2 t2
where t1.id = '1'
and t2.id = t1.id
and t1.id2 != t2.id2
You can use a LEFT OUTER JOIN:
select t1.*
from table1 t1
LEFT OUTER JOIN table2 t2
ON t1.id = t2.id
WHERE t2.id IS NULL
LEFT OUTER JOIN says to take all results from the LEFT-most table (table1 here) and only those results from your joined table (table2 here) that match the ON condition. By filtering in your WHERE clause to drop any results where table2.id IS NULL you effectively only leave T1 results that are unmatched to T2.
Also try to stay away from the FROM table1, table2 type of implicit join. It's very old school. INNER JOIN, LEFT OUTER JOIN, RIGHT OUTER JOIN are better options for nearly any situation.

Whats wrong with my cte and insert command

Its just a basic cte with inner join and insert command dont know what is the mistake I did please help
My table t1
ID Name
1 A
2 B
3 C
My table t2
ID Name
1 A
2 B
What I'm trying to do is, inner join two table and take unmatched records. Insert the unmatched record into table t2. This is what I wrote
with scd(scdid,scdname)
as
(select t1.id as scdid, t1.name as scdname from t1 where t1.id not in (select t1.id from t1 inner join t2 on t1.id = t2.id))
insert into t2(id,name) select scd.scdid, scd.scdname from scd;
Something went wrong it says
SQL Error: ORA-00928: missing SELECT keyword
00928. 00000 - "missing SELECT keyword"
Please help, it must be simple mistake i guess
Edit: apologies for the mistake, yes I'm using Oracle server.
Here is the query:
with scd(scdid, scdname) as
(select t1.id as scdid, t1.name as scdname
from t1
where t1.id not in (select t1.id from t1 inner join t2 on t1.id = t2.id)
)
insert into t2(id, name)
select scd.scdid, scd.scdname
from scd;
This query looks syntactically correct for SQL Server. However, you have an Oracle error. Try writing the query as:
insert into t2(id, name)
select t1.id as scdid, t1.name as scdname
from t1
where t1.id not in (select t1.id from t1 inner join t2 on t1.id = t2.id);
Or better yet as:
insert into t2(id, name)
select t1.id as scdid, t1.name as scdname
from t1
where t1.id not in (select t2.id from t2);
Note that the Oracle syntax for a CTE with an insert is to place the with after the insert. However, a CTE is not needed for this.
EDIT: In Oracle syntax:
insert into t2(id, name)
with scd(scdid, scdname) as
(select t1.id as scdid, t1.name as scdname
from t1
where t1.id not in (select t1.id from t1 inner join t2 on t1.id = t2.id)
)
select scd.scdid, scd.scdname
from scd;
In Oracle, the with statement is part of a select.

Join query where table references itself

I'm using Oracle 10, but the best way to ask this question is with an example.
select *
from t1, t2
where t1.id = t2.id
and t1.otherID = (select max(otherID)
from t2
where id = THE ID FROM THE OUTER QUERY T1
)
I think you see where I'm trying to go with this. I need to reference t1 in the subquery to join it to the max of t2.
I need to know how to create a query like this.
"THE ID FROM THE OUTER QUERY T1" is where my confusion is.
I tried using t1.id, but did not get results.
Try the following
select t1.*, t2.*
from t1
join t2 on t1.id = t2.id
join (select id, max(otherID) as max_otherID
from t2
group by id
) a ON a.id = t1.id and a.max_otherID = t1.otherID
Using a sub-query on the join often gives better performance than using it in the where clause.