Parameterize the Decode Function - oracle

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
);

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!!

ORACLE - Update Multiple Columns with Values from Nested Join

I'm practically new in using oracle and I bumped into a blocker. Below is the query that I created based on what I have researched online to update multiple columns of a table with values from a nested join statement.
UPDATE
(
SELECT
A.COLUMN1 OLD_COLUMN1,
BC.COLUMN1 NEW_COLUMN1,
A.BALANCE OLD_COLUMN2,
BC.COLUMN2_MIN NEW_COLUMN2,
A.COLUMN3 OLD_COLUMN3,
BC.COLUMN3 NEW_COLUMN3
FROM TABLE_A A
INNER JOIN
(
SELECT B.TWWID,
B.ITEMDATE,
B.COLUMN2_MIN,
C.COLUMN3,
C.COUNTRYID,
C.COLUMN1
FROM TABLE_B B
LEFT OUTER JOIN TABLE_C C
ON TO_CHAR(B.ID) = TO_CHAR(C.ID)
) BC
ON A.ID = BC.ID
AND A.DATE = BC.DATE
)ABCUPDATE
SET ABCUPDATE.OLD_COLUMN1 = ABCUPDATE.NEW_COLUMN1,
ABCUPDATE.OLD_COLUMN2 = ABCUPDATE.NEW_COLUMN2,
ABCUPDATE.OLD_COLUMN3 = ABCUPDATE.NEW_COLUMN3;
Selecting the sub-query returns the expected results but when I run the update script as a whole an error is returned.
ORA-01779: cannot modify a column which maps to a non key-preserved
table
Can anyone please explain why I encounter this error and what adjustments can I do to the script to make it work?
Thanks in advance!

Right join with group by clause in 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.

PL SQL - Join 2 tables and return max from right table

Trying to retrive the MAX doc in the right table.
SELECT F43.PDDOCO,
F43.PDSFXO,
F43.PDLNID,
F43.PDAREC/100 As Received,
F431.PRAREC/100,
max(F431.PRDOC)
FROM PRODDTA.F43121 F431
LEFT OUTER JOIN PRODDTA.F4311 F43
ON
F43.PDKCOO=F431.PRKCOO
AND F43.PDDOCO=F431.PRDOCO
AND F43.PDDCTO=F431.PRDCTO
AND F43.PDSFXO=F431.PRSFXO
AND F43.PDLNID=F431.PRLNID
WHERE F431.PRDOCO = 401531
and F431.PRMATC = 2
and F43.PDLNTY = 'DC'
Group by
F43.PDDOCO,
F43.PDSFXO,
F43.PDLNID,
F43.PDAREC,
F431.PRAREC/100
This query is still returning the two rows in the right table. Fairly new to SQL and struggling with the statement. Any help would be appreciated.
Without seeing your data it is difficult to tell where the problem might so I will offer a few suggestions that could help.
First, you are joining with a LEFT JOIN on the PRODDTA.F4311 but you have in the WHERE clause a filter for that table. You should move the F43.PDLNTY = 'DC' to the JOIN condition. This is causing the query to act like an INNER JOIN.
Second, you can try using a subquery to get the MAX(PRDOC) value. Then you can limit the columns that you are grouping on which could eliminate the duplicates. The query would them be similar to the following:
SELECT F43.PDDOCO,
F43.PDSFXO,
F43.PDLNID,
F43.PDAREC/100 As Received,
F431.PRAREC/100,
F431.PRDOC
FROM PRODDTA.F43121 F431
INNER JOIN
(
-- subquery to get the max
-- then group by the distinct columns
SELECT PDKCOO, max(PRDOC) MaxPRDOC
FROM PRODDTA.F43121
WHERE PRDOCO = 401531
and PRMATC = 2
GROUP BY PDKCOO
) f2
-- join the subquery result back to the PRODDTA.F43121 table
on F431.PRDOC = f2.MaxPRDOC
AND F431.PDKCOO = f2.PDKCOO
LEFT OUTER JOIN PRODDTA.F4311 F43
ON F43.PDKCOO=F431.PRKCOO
AND F43.PDDOCO=F431.PRDOCO
AND F43.PDDCTO=F431.PRDCTO
AND F43.PDSFXO=F431.PRSFXO
AND F43.PDLNID=F431.PRLNID
AND F43.PDLNTY = 'DC' -- move this filter to the join instead of the WHERE
WHERE F431.PRDOCO = 401531
and F431.PRMATC = 2
If you provide your table structures and some sample data, it will be easier to determine the issue.

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