Right join with group by clause in oracle - oracle

Please share me your input on below
I have two dataset in oracle 11g
set 1:
empid-Qtr-salary
1-Q3FY16-2000
1-Q2FY16-1000
2-Q3FY16-2000
2-Q2FY16-3000
2-Q1FY16-4000
2-Q4FY15-5000
3-Q2FY16-7000
3-Q1FY16-8000
enter code here
set 2
id-qtr
1-Q3FY16
2-Q2FY16
3-Q1FY16
4-Q4FY15
EXPECTED OUTPUT IS
enter code here
1-Q3FY16-2000
1-Q2FY16-1000
1-Q1FY16-NULL
1-Q4FY15-NULL
2-Q3FY16-2000
2-Q2FY16-3000
2-Q1FY16-4000
2-Q4FY15-5000
3-Q3FY16-NULL
3-Q2FY16-3000
3-Q1FY16-7000
3-Q4FY15-NULL
tried with right out join . No luck.
select s1.empid,s2.qtr,s1.salary from set1 s1
right join set2 s2 on s2.qtr=s1.qtr
group by s1.empid,s2.qtr,s1.salary

The right outer join you want is with the CROSS JOIN of the list of empid's (which should be in a table of its own) and the list of quarters. Something like this:
select s1.empid, s1.qtr, s1.salary
from s1 right other join
((select distinct empid from s1) s3 cross join s2) t
on s1.empid = t.empid and s1.qtr = t.qtr
For every PAIR (empid, qtr) you want to pick up the salary, and if there is no salary, you want NULL instead - that's what the right outer join does. The cross join creates the set of ALL possible combinations of empid and qtr.

Related

Join to another table when the join column is null

I have a sql that is selecting many things from the database however I would like that data to only comeback which is matched to a personal table I have.
I would like to join a column [vin_code] from my table [population] however there are nulls in here and were there are nulls I would like to join another column from my table to another table in the database.
I will give an example sql below:
Select distinct v.kegal_rntity_id
From vin v
Inner join ops$dami.population pop
On v.vin_code = pop.vin_code
Then were pop.vin_code is null I would like to join pop.vis_code on a table in the database called zegal_rentity z column z.vis_code
So something like
join zegal_rentity z
On pop.vis_code = z.vis_code
But I only want to do this were pop.vin_code is null
As sample data is not available, I am unable to test the solution but try the following query with condition based outer join.
Select distinct v.kegal_rntity_id
From ops$dami.population pop
Left join vin v
On v.vin_code = pop.vin_code
Left join zegal_rentity z
On (case when pop.vin_code is null and
pop.vis_code = z.vis_code then 1 end = 1);
Cheers!!

how to get the count(id) from the multiple tables using join query

I want to display count based on the id from multiple tables. for two tables it is working fine but for three tables it is not displaying data
this is my query for three tables it is not working
select r.req_id
, r.no_of_positions
, count(j.cand_id) as no_of_closure
, count(cis.cand_id)
from requirement r
join joined_candidates j
on r.req_id=j.req_id
join candidate_interview_schedule cis
on cis.req_id=r.req_id
where cis.interview_status='Interview Scheduled'
group by r.req_id, r.no_of_positions;
Changed to left joins incase value doens't exist in a table
Changed count to use an window function so counts are not artificially inflated by joins
moved where clause to join criteria as on a left join, it would negate the null values, making it operate like a inner join.
..MAYBE...
SELECt r.req_id
, r.no_of_positions
, count(j.cand_id) over (partition by J.cand_ID) as no_of_closure
, count(cis.cand_id) over (partition by cis.cand_id) as no_of_CIS_CNT
FROM requirement r
LEFT join joined_candidates j
on r.req_id=j.req_id
LEFT join candidate_interview_schedule cis
on cis.req_id=r.req_id
and cis.interview_status='Interview Scheduled'
GROUP BY r.req_id, r.no_of_positions;
or perhaps... (if I can assume j.cand_ID and cis.cand_ID are unique) also to eliminate artificial count increase due to 1:M joins
SELECt r.req_id
, r.no_of_positions
, count(distinct j.cand_id) as no_of_closure
, count(distinct cis.cand_id) as no_of_CIS_CNT
FROM requirement r
LEFT join joined_candidates j
on r.req_id=j.req_id
LEFT join candidate_interview_schedule cis
on cis.req_id=r.req_id
and cis.interview_status='Interview Scheduled'
GROUP BY r.req_id, r.no_of_positions;

Parameterize the Decode Function

In a oracle i'm using a Decode Statement as below. For security reasons i don't want the code to have the hardcoded values and i plan to create a new lookup table.
Select CONCAT( Decode(A.COUNTRY_INITIAL,
'A','America',
'B','Brazil',
'F','FINLAND',
NULL),
Decode(A.ADD_VALUE,
'M','YES',
NULL))
from (
Select SUBSTR(COUNTRY_BASE, -1,1) as COUNTRY_INITIAL,
SUBSTR(IS_VALUED, -1,1) as ADD_VALUE
from TBL1
)A
Refernece Table
*******************
Clmn1 Clmn2 Clmn3
--------------------------
cntry1 A America
cntry2 B Brazil
cntry3 F Finland
Value1 M YES
Could you please let me know how i can incorporate this in the decode logic. Also fyi im using this CODE SNIPPET in a Oracle Function.
If you're going to store the lookup information in a table, you wouldn't use a DECODE. You'd join the two tables
SELECT ref.clmn3
FROM tbl1 t1
LEFT OUTER JOIN <<reference table>> ref
ON( substr(t1.country_base, -1, 1) = ref.clmn2 )
Since your DECODE has a NULL, I'm guessing that you are expecting that some rows of tbl1 will not have a matching row in the reference table so I'm guessing that you want a LEFT OUTER JOIN rather than an INNER JOIN.
If you have these details in a table you can simply use a join to get desired output.
select t1.COUNTRY_BASE,ref.Clmn3,ref1.Clmn3
frorm TBL1 t1
left outer join reftable ref
on SUBSTR(t1.COUNTRY_BASE, -1,1)=ref.Clmn2
left outer join reftable ref1
on SUBSTR(t1.IS_VALUED, -1,1)=ref.Clmn2;
If your are using separate table to store the values, you don't need decode function. You can simply join the two tables.
select a.country_base,
a.is_valued,
b.clmn3,
c.clmn3
from tbl1 a left outer join reference_table b
on (substr(a.country_base, -1, 1) = b.clmn2
and b.clmn1 like 'cntry%' --extra clause needed if there are same country and value codes
)
left outer join reference_table c
on (substr(a.is_valued, -1, 1) = c.clmn2
and c.clmn1 like 'Value%' --extra clause needed if there are same country and value codes
);

Hive doesn't support in, exists. How do I write the following query?

I have two tables A and B that both have a column id. I wish to obtain ids from A that are not present in B. The obvious way is:
SELECT id FROM A WHERE id NOT IN (SELECT id FROM B)
Unfortunately, Hive doesn't support in, exists or subqueries. Is there a way to achieve the above using joins?
I thought of the following
SELECT A.id FROM A,B WHERE A.id<>B.id
But it seems like this will return the entirety of A, since there always exists an id in B that is not equal to any id in A.
You can do the same with a LEFT OUTER JOIN in Hive:
SELECT A.id
FROM A
LEFT OUTER JOIN B
ON (B.id = A.id)
WHERE B.id IS null
Hive seems to support IN, NOT IN, EXIST and NOT EXISTS from 0.13.
select count(*)
from flight a
where not exists(select b.tailnum from plane b where b.tailnum = a.tailnum);
The subqueries in EXIST and NOT EXISTS should have correlated predicates (like b.tailnum = a.tailnum in above sample)
For more, refer Hive Wiki > Subqueries in the WHERE Clause
Should you ever want to do an IN as so:
SELECT id FROM A WHERE id IN (SELECT id FROM B)
Hive has this covered with a LEFT SEMI JOIN:
SELECT a.key, a.val
FROM a LEFT SEMI JOIN b on (a.key = b.key)
if you can using spark sql you can use left anti join.
ex: SELECT A.id FROM A left anti join B on a.id=b.id

Oracle : How to use if then in a select statement

select ma.TITLE,ma.ID as aid,ur.USER_ID
from LEO_MENU_ACTIVITY_RELATION mr
inner join LEO_MENU_MASTER mm on mm.ID=mr.MENU_ID
INNER join LEO_MENUACTIVITY ma on mr.ACTIVITY_ID=ma.ID
LEFT OUTER JOIN LEO_USER_RIGHTS ur on ma.ID=ur.MENU_RELATION_ID and ur.MENU_ID=mm.ID and ur.USER_ID='141'
where mm.ID='1'
UNION (SELECT
'List' as TITLE,
1 as ID,
case (WHEN ur.MENU_RELATION_ID=1 THEN NULL ELSE USER_ID END)as USER_ID
from
LEO_USER_RIGHTS)
In the UNION i want perform a conditional select like if ur.MENU_RELATION_ID=1 then the USER_ID should be selected as NULL otherwise the the original value from the 'LEO_USER_RIGHTS' table must be retrieved.
How can i do this ? Please help
Krishnik
If you want to combine in a UNION something based on the first table I think you can only do it by repeating the whole thing like this:
select ma.TITLE,ma.ID as aid,ur.USER_ID
from LEO_MENU_ACTIVITY_RELATION mr
inner join LEO_MENU_MASTER mm on mm.ID=mr.MENU_ID
INNER join LEO_MENUACTIVITY ma on mr.ACTIVITY_ID=ma.ID
LEFT OUTER JOIN LEO_USER_RIGHTS ur on ma.ID=ur.MENU_RELATION_ID and ur.MENU_ID=mm.ID and ur.USER_ID='141'
where mm.ID='1'
UNION (SELECT
'List' as TITLE,
1 as ID,
case (WHEN ur.MENU_RELATION_ID=1 THEN NULL ELSE USER_ID END)as USER_ID
from
LEO_MENU_ACTIVITY_RELATION mr
inner join LEO_MENU_MASTER mm on mm.ID=mr.MENU_ID
INNER join LEO_MENUACTIVITY ma on mr.ACTIVITY_ID=ma.ID
LEFT OUTER JOIN LEO_USER_RIGHTS ur on ma.ID=ur.MENU_RELATION_ID and ur.MENU_ID=mm.ID and ur.USER_ID='141'
where mm.ID='1'
)
If this is used often I would create a view to avoid duplicate code. In ORACLE (I do not know for other SQL dialects) there is a WITH statement enables you to make a sort of "temporary view".

Resources