Covert left join to simple join - sql

My LEFT JOIN subquery is taking longer. How do I covert it to JOIN?
SELECT * FROM "TABLE_A"
LEFT OUTER JOIN TABLE_B ON TABLE_A.mainid = TABLE_B.secondID
LEFT JOIN (
SELECT secondID
FROM TABLE_C
WHERE thirdID = 21
) Z ON TABLE_A.mainid = Z.secondID
WHERE "TABLE_A"."TRUEID" = 9
AND ((TABLE_A.USERNO IN (23))

First, write the query more concisely:
SELECT *
FROM "TABLE_A" a LEFT JOIN
TABLE_B b
ON a.mainid = b.secondID LEFT JOIN
TABLE_C c
ON a.mainid = c.secondID AND c.thirdID = 21
WHERE a."TRUEID" = 9 AND a.USERNO IN (23);
Then consider the indexes:
Table_A(TRUEID, USERNO, mainid)
Table_B(secondID)
Table_C(secondID, thirdID)

Related

Table Self join

Table_a has columns : old_id and new_id . Following query gives planning region and organization code for old_id.
SELECT a.old_id,d.planning_region,b.organization_code
FROM table_a a
INNER JOIN table_b b ON a.old_id = b.organization_id
INNER JOIN table_c c ON c.organization_code = b.organization_code
INNER JOIN table_d d ON d.planning_location_id = b.organization_code
My requirement is get organization code for new_id too. So my output will be like this
old_id, planning_region ( of old_id ), organization_code (of old_id ) and organization_code (of new_id ).
Self Join should work but here in this case, Do I need to do self join of all 4 tables ?
Note: new_id also can be joined same as old_id with table_b.
If I am understanding correctly, you can add more joins.
If you just want the new organization_code:
SELECT
a.old_id,
d.planning_region,
b.organization_code,
b1.organization_code organization_code_new
FROM table_a a
INNER JOIN table_b b ON a.old_id = b.organization_id
INNER JOIN table_c c ON c.organization_code = b.organization_code
INNER JOIN table_d d ON d.planning_location_id = b.organization_code
INNER JOIN table_b b1 ON a.new_id = b1.organization_id
If you also want the planning_region, then we need to bring d as well:
SELECT
a.old_id,
d.planning_region,
b.organization_code,
d1.planning_region planning_region_new,
b1.organization_code organization_code_new
FROM table_a a
INNER JOIN table_b b ON a.old_id = b.organization_id
INNER JOIN table_c c ON c.organization_code = b.organization_code
INNER JOIN table_d d ON d.planning_location_id = b.organization_code
INNER JOIN table_b b1 ON a.new_id = b1.organization_id
INNER JOIN table_c c1 ON a.new_id = c1.organization_id
INNER JOIN table_d d1 ON d1.planning_location_id = b1.organization_code
Side note: it is not obvious what the purpose of table c is in the query (apart, maybe, filtering?).

Oracle JOIN in cursor only if a certain metadata is found for input parameter

I have a cursor with a join like so:
CURSOR C1 IS
SELECT *
FROM table_1 a
JOIN table_2 b
ON b.ID_1 = a.ID_1
WHERE TABLE_ID IS NOT NULL
AND TABLE_ID = p_input_id;
I want to modify the cursor and add 3 more joins only if p_input_id IS found in a metadata table. So I want to do something like this:
CURSOR C1 IS
SELECT *
FROM table_1 a
JOIN table_2 b
ON b.ID_1 = a.ID_1
CASE
WHEN EXISTS (SELECT 1
FROM METADATA_TABLE
WHERE INPUT_ID = p_input_id
AND FLAG = 'Y')
THEN
JOIN table_3 c
ON c.ID_2 = b.ID_2
JOIN table_4 d
ON d.ID_3 = c.ID_3
END
WHERE TABLE_ID IS NOT NULL
AND TABLE_ID = p_input_id;
How can I accomplish this? I could consider using LEFT JOIN instead of the case/join. Are there any issues with this?
CURSOR C1 IS
SELECT *
FROM table_1 a
JOIN table_2 b
ON b.ID_1 = a.ID_1
LEFT JOIN table_3 c
ON c.ID_2 = b.ID_2
LEFT JOIN table_4 d
ON d.ID_3 = c.ID_3
WHERE TABLE_ID IS NOT NULL
AND TABLE_ID = p_input_id;
I'm trying to avoid breaking the current cursor for the p_input_id's which are using it. There will be new p_input_id's which need to use the extra table joins.
You can use LEFT JOIN for table_3 and table_4 and count in metadata table as follows:
SELECT * FROM TABLE_1 A
JOIN TABLE_2 B ON B.ID_1 = A.ID_1
JOIN ( SELECT COUNT(1) AS CNT
FROM METADATA_TABLE
WHERE INPUT_ID = P_INPUT_ID
AND FLAG = 'Y') MT
LEFT JOIN TABLE_3 C ON C.ID_2 = B.ID_2
AND MT.CNT > 0
JOIN TABLE_4 D ON D.ID_3 = C.ID_3
AND MT.CNT > 0
WHERE TABLE_ID IS NOT NULL
AND TABLE_ID = P_INPUT_ID;
COUNT is used in the metadata table to ensure that it returns only one record.(replacement of exists)

How to get the column which are not in inner join sql, using union all is time lot of time

I have 2 tables with same columns and have them inner join as below, I m trying to get the columns that are not taken in the inner join. I will be using this in a spark-sql code.
select A.pension, B.pension
from Db1.table1 A, Db2.table2 B
where to_date(A.rdt) = '2019-06-20' and A.state = 'ohio' and A.empno= B.empno;
I have tried using UNION ALL, but taking more time than system timeout, didnt add the clauses.
select A.pension
from Db1.table1 A left outer join
Db2.table2 B
on A.pension = B.pension
where B.pension is null
UNION ALL
select B.pension
from Db2.table2 A left outer join
Db1.table1 B
on A.pension = B.pension
where A.pension is null;
I have also tried using full outer join, taking time too, query didnt run.
select A.pension, B.pension
from Db1.table1 A full outer join
Db2.table2 B
on A.empno = B.empno
where to_date(A.rdt) = '2019-06-20' and A.state = 'ohio' and A.pension = NULL or B.pension = NULL
rdt is in timestamp, pension int, empno int,
We just want the records which are not picked by the inner join, output must be a table with columns A.pension, B.pension, only has the records that are not matching in those two columns.
Full outer join is tricky when using filtering. I recommend doing the filtering in a subquery:
select A.pension, B.pension
from (select A.*
from Db1.table1 A
where to_date(A.rdt) = '2019-06-20' and A.state = 'ohio'
) A full outer join
Db2.table2 B
on A.empno = B.empno
where A.pension = NULL or B.pension = NULL

order of join in hive

I have a query which involves a left join followed by a join. I want to make sure the left join is done first. The left join comes before the join nin my query, is this enough? This is how the join looks like
select * from
(select *....) A
left join
(select *...) B
on A.a = B.a
left join
C
on A.f = C.f
I cannot see the JOIN in your code, only two LEFT JOIN statements.
However, if you have something like this:
select * from
(select *....) A
left join
(select *...) B
on A.a = B.a
join
C
on A.f = C.f
and you want to make sure the LEFT JOIN is executed first, you can move this LEFT JOIN to a sub-query:
select *
from (
select * from (
(select *....) A
left join
(select *...) B
on A.a = B.a
)
) D
join
C
on D.f = C.f

Oracle SQL - left join + left outer join

I am querying three tables. TABLE1 A and TABLE2 B have a one-to-one ratio on DEPTID. TABLE3 C, however, does not hold 0 values. I can successfully get COUNT to give me 0 values from TABLE3 C when doing a LEFT OUTER JOIN with TABLE1 A or TABLE2 B, but it gives me (null) instead of 0 when I join all three tables together. I need it to return 0 instead of (null). Any help is very much appreciated:
SELECT A.DEPTID, B.DEPT_NAME, SUM(C.HEAD_COUNT)
FROM TABLE1 A
LEFT JOIN TABLE2 B ON A.DEPTID = B.DEPTID
LEFT OUTER JOIN TABLE3 C ON A.POSITION_NUMBER = C.POSITION_NUMBER
GROUP BY A.DEPTID, B.DEPT_NAME
Here is what I am currently getting:
Dept 1: headcount 9
Dept 2: headcount 11
Dept 3: (null)
Use COALESCE() or NVL() to substitute 0 for NULL values:
SELECT A.DEPTID,
B.DEPT_NAME,
SUM(COALESCE( C.HEAD_COUNT, 0 ) )
FROM TABLE1 A
LEFT OUTER JOIN TABLE2 B
ON A.DEPTID = B.DEPTID
LEFT OUTER JOIN TABLE3 C
ON A.POSITION_NUMBER = C.POSITION_NUMBER
GROUP BY A.DEPTID,
B.DEPT_NAME