Assistance replacing oracle (+) joins to ANSI joins - oracle

I've reviewed other posts as well as Oracle documentation on replacing the older style (+) joins with ANSI format joins. I'm having a hard time converting this over to what I assume to be two left outer join operations. My hangup is the two from select statements and where exactly the joins should be placed.
Here is my query:
SELECT
AUP.USERNAME,
AUP.MENU_STRING MODULE,
NVL(UGA.PERMISSION,AUP.DEFAULT_PERMISSION) PERMISSION
FROM
(SELECT
DU.USERNAME,
A.PROGRAM_ID,
A.MENU_STRING,
'Y' DEFAULT_PERMISSION
FROM
APPLICATION A,
DBA_USERS DU
WHERE
A.PROGRAM_ID NOT IN ('.SEPARATOR')
AND DU.USERNAME NOT LIKE '%#') AUP,
(SELECT
USER_ID,
PROGRAM_ID,
PERMISSION
FROM
USER_PGM_AUTHORITY
WHERE
PROGRAM_COMPONENT='PROGRAM') UGA
WHERE
AUP.USERNAME=UGA.USER_ID(+)
AND AUP.PROGRAM_ID=UGA.PROGRAM_ID(+)
AND aup.menu_string = 'Vendor Maintenance'
ORDER BY
AUP.USERNAME,
AUP.MENU_STRING;

I think this will do it:
SELECT
AUP.USERNAME,
AUP.MENU_STRING MODULE,
NVL(UGA.PERMISSION,AUP.DEFAULT_PERMISSION) PERMISSION
FROM
(SELECT
DU.USERNAME,
A.PROGRAM_ID,
A.MENU_STRING,
'Y' DEFAULT_PERMISSION
FROM
APPLICATION A,
DBA_USERS DU
WHERE
A.PROGRAM_ID NOT IN ('.SEPARATOR')
AND DU.USERNAME NOT LIKE '%#') AUP
LEFT JOIN
(SELECT
USER_ID,
PROGRAM_ID,
PERMISSION
FROM
USER_PGM_AUTHORITY
WHERE
PROGRAM_COMPONENT='PROGRAM') UGA
ON
AUP.USERNAME=UGA.USER_ID
AND AUP.PROGRAM_ID=UGA.PROGRAM_ID
WHERE
aup.menu_string = 'Vendor Maintenance'
ORDER BY
AUP.USERNAME,
AUP.MENU_STRING;

The join is between AUPand UGA:
SELECT
AUP.USERNAME,
AUP.MENU_STRING MODULE,
NVL(UGA.PERMISSION,AUP.DEFAULT_PERMISSION) PERMISSION
FROM
(SELECT
DU.USERNAME,
A.PROGRAM_ID,
A.MENU_STRING,
'Y' DEFAULT_PERMISSION
FROM
APPLICATION A,
DBA_USERS DU
WHERE
A.PROGRAM_ID NOT IN ('.SEPARATOR')
AND DU.USERNAME NOT LIKE '%#') AUP
LEFT JOIN
(SELECT
USER_ID,
PROGRAM_ID,
PERMISSION
FROM
USER_PGM_AUTHORITY
WHERE
PROGRAM_COMPONENT='PROGRAM') UGA
ON AUP.USERNAME=UGA.USER_ID
AND AUP.PROGRAM_ID=UGA.PROGRAM_ID
WHERE aup.menu_string = 'Vendor Maintenance'
ORDER BY
AUP.USERNAME,
AUP.MENU_STRING;

You can refactor it using named sub-queries to make it more readable:
WITH AUP AS ( -- Moved to a named sub-query
SELECT
DU.USERNAME,
A.PROGRAM_ID,
A.MENU_STRING,
'Y' DEFAULT_PERMISSION
FROM
APPLICATION A
CROSS JOIN -- No apparent join condition so used an explicit CROSS JOIN.
DBA_USERS DU
WHERE
A.PROGRAM_ID NOT IN ('.SEPARATOR')
AND DU.USERNAME NOT LIKE '%#'
AND A.MENU_STRING = 'Vendor Maintenance' -- Moved to the appropriate sub-query
),
UGA AS ( -- Moved to a named sub-query
SELECT
USER_ID,
PROGRAM_ID,
PERMISSION
FROM
USER_PGM_AUTHORITY
WHERE
PROGRAM_COMPONENT='PROGRAM'
)
SELECT
AUP.USERNAME,
AUP.MENU_STRING MODULE,
NVL(UGA.PERMISSION,AUP.DEFAULT_PERMISSION) PERMISSION
FROM
AUP
LEFT OUTER JOIN
UGA
ON ( AUP.USERNAME =UGA.USER_ID
AND AUP.PROGRAM_ID=UGA.PROGRAM_ID )
ORDER BY
AUP.USERNAME,
AUP.MENU_STRING;

Borrowing this thread from 10 years ago. I've tried to adapt the solution to my query but I can't figure it out.
Here is my query and I want to replace the (+) with LEFT JOIN
FROM a,b,c
WHERE b.a = '101'
AND a.a = '202'
AND b.c = a.c
AND a.d = c.d(+)
AND ROWNUM = 1;

Related

Issue With GROUP BY In Query

First of all, thanks in advance for any help anyone can offer!
I'm fairly new to Oracle, so I apologize if this question is stupid...
I'm having an issue getting a query to run properly, and the issue is with the GROUP BY clause in the query.
When running the query, I get the error stating that it's not a GROUP BY statement?? Not really sure what that means.
Here is the query:
with SUB_GRP_LVL_1 as
(
select sg.HCC_ID,sge.SUB_GROUP_NAME
from XXXX_ODS.GROUP_T g
Join XXXX_ODS.SUB_GROUP sg
on g.GROUP_KEY=sg.GROUP_KEY
and g.HCC_ID NOT IN('A0002','A0003','A0004','A0005','A0021','A0022','A0041','A0042','A0081','A0121','A0061')
and sg.REC_SRC_CD='HS1'
and sg.LEVEL_NBR=1
join XXXX_ODS.SUB_GROUP_EFF sge
on sge.SUB_GROUP_KEY=sg.SUB_GROUP_KEY
---and sge.CURRENT_INDC=1
and sge.ACTIVE_INDC=1
)
,
SUB_GRP_LVL_2 as
(
select sg.HCC_ID,sge.SUB_GROUP_NAME
from XXXX_ODS.GROUP_T g
Join XXXX_ODS.SUB_GROUP sg
on g.GROUP_KEY=sg.GROUP_KEY
and g.HCC_ID NOT IN('A0002','A0003','A0004','A0005','A0021','A0022','A0041','A0042','A0081','A0121','A0061')
and sg.REC_SRC_CD='HS1'
and sg.LEVEL_NBR=2
join XXXX_ODS.SUB_GROUP_EFF sge
on sge.SUB_GROUP_KEY=sg.SUB_GROUP_KEY
and sge.ACTIVE_INDC=1
)
,
GRP_BEN_PL_ID as
(
select sg.SUB_GROUP_KEY,bpe.HCC_BENEFIT_PLAN_ID , sgbp.EFFECTIVE_DT, sgbp.EXPIRATION_DT, pe.FUNDING_TYPE, pe.HCC_PROD_ID, pe.STATE_CD, pe.SUB_COMPANY
from XXXX_ODS.GROUP_T g
Join XXXX_ODS.SUB_GROUP sg
on g.GROUP_KEY=sg.GROUP_KEY
and g.HCC_ID NOT IN('A0002','A0003','A0004','A0005','A0021','A0022','A0041','A0042','A0081','A0121','A0061')
and g.REC_SRC_CD='HS1'
JOIN XXXX_ODS.SUB_GROUP_BENEFIT_PLAN sgbp
on sg.SUB_GROUP_KEY=sgbp.SUB_GROUP_KEY
---and sgbp.CURRENT_INDC=1
and sgbp.ACTIVE_INDC=1
join XXXX_ODS.BENEFIT_PLAN_EFF bpe
on sgbp.BENEFIT_PLAN_KEY = bpe.BENEFIT_PLAN_KEY
and bpe.ACTIVE_INDC=1
join XXXX_ods.product_eff pe
on bpe.PRODUCT_KEY=pe.product_key
and pe.ACTIVE_INDC=1
)
select
BLK_1.SUB_GROUP_KEY,ACCT_NBR AS GROUPID,
SUB_GRP_ID,
DIVISION_ID
,GRP_BEN_PL_ID.HCC_BENEFIT_PLAN_ID
,INVOICE_NBR
,'CMD' BUSTYPE,
GRP_BEN_PL_ID.FUNDING_TYPE AS BUSSUBTYPE,
GRP_BEN_PL_ID.HCC_PROD_ID AS PROCODE,
'' AS PREMIUMTYPE,
INV.CURRENT_INVOICED_AMT AS PREMIUMBILLED,
INV.CURRENT_INVOICED_AMT AS PREMIUMDUEDATE,
'' AS PREMIUMPAID,
'' AS PREMIUMAPPLYDATE,
COUNT(invl.INVOICE_LINE_KEY) AS CONTRACTSXXXXL,
'' AS MEMBERSXXXXL
--ACCOUNT_TYPE
,DECODE (UPPER(GRP_BEN_PL_ID.STATE_CD),'NEBRASKA','NE','IOWA','IA') STATE,
GRP_BEN_PL_ID.SUB_COMPANY LGL_ENTITY,
LEVEL_NBR
from
(
select
g.GROUP_KEY, sg.SUB_GROUP_KEY, g.HCC_ID ACCT_NBR,ge.GROUP_NAME ACCT_NAME,substr(sg.HCC_ID, 1,instr(sg.hcc_id,'-',1,2)-1) SUB_GRP_ID,sg.HCC_ID DIVISION_ID,ce.FIRST_EFFECTIVE_DT,
add_months(
decode(ce.EFFECTIVE_DT,TO_DATE('01/01/1800','MM/DD/YYYY'),ce.FIRST_EFFECTIVE_DT,ce.EFFECTIVE_DT),ce.RENEWAL_INTERVAL) RENVL_DT, ce.ACCOUNT_TYPE
, sg.LEVEL_NBR
from
XXXX_ODS.CUSTOMER_EFF ce
join XXXX_ODS.GROUP_T g
on g.CUSTOMER_KEY=ce.CUSTOMER_KEY
Join XXXX_ODS.SUB_GROUP sg
on g.GROUP_KEY=sg.GROUP_KEY
and g.HCC_ID NOT IN('A0002','A0003','A0004','A0005','A0021','A0022','A0041','A0042','A0081','A0121','A0061')
and g.REC_SRC_CD='HS1'
and sg.LEVEL_NBR=2
and g.HCC_ID not like 'TEST%'
join XXXX_ODS.GROUP_EFF ge
on ge.GROUP_KEY = g.GROUP_KEY
and ge.CURRENT_INDC=1
union
select
gp.GROUP_KEY,
sgp.SUB_GROUP_KEY, gp.HCC_ID ACCT,gep.GROUP_NAME, sgp.HCC_ID SUB_GRP, NULL DIVISION,cep.FIRST_EFFECTIVE_DT,
add_months(decode(cep.EFFECTIVE_DT,TO_DATE('01/01/1800','MM/DD/YYYY'),cep.FIRST_EFFECTIVE_DT,cep.EFFECTIVE_DT),cep.RENEWAL_INTERVAL) RENVL_DT,
cep.ACCOUNT_TYPE, sgp.LEVEL_NBR
from
XXXX_ODS.CUSTOMER_EFF cep
join XXXX_ODS.GROUP_T gp
on gp.CUSTOMER_KEY=cep.CUSTOMER_KEY
Join XXXX_ODS.SUB_GROUP sgp
on gp.GROUP_KEY=sgp.GROUP_KEY
and gp.HCC_ID NOT IN('A0002','A0003','A0004','A0005','A0021','A0022','A0041','A0042','A0081','A0121','A0061')
and gp.REC_SRC_CD='HS1'
and sgp.LEVEL_NBR=1
and gp.HCC_ID not like 'TEST%'
join XXXX_ODS.GROUP_EFF gep
on gep.GROUP_KEY = gp.GROUP_KEY
and gep.CURRENT_INDC=1
and not exists
(
select 'X'
from
XXXX_ODS.GROUP_T gi
Join XXXX_ODS.SUB_GROUP sgi
on gi.GROUP_KEY=sgi.GROUP_KEY
and gi.HCC_ID NOT IN('A0002','A0003','A0004','A0005','A0021','A0022','A0041','A0042','A0081','A0121','A0061')
and gi.REC_SRC_CD='HS1'
and sgi.LEVEL_NBR=2
and gi.HCC_ID not like 'TEST%'
where
gp.HCC_ID=gi.HCC_ID
and sgp.HCC_ID=substr(sgi.HCC_ID, 1,instr(sgi.hcc_id,'-',1,2)-1)
)
) BLK_1
join SUB_GRP_LVL_1
on SUB_GRP_LVL_1.HCC_ID=BLK_1.SUB_GRP_ID
left join SUB_GRP_LVL_2
on SUB_GRP_LVL_2.HCC_ID=BLK_1.DIVISION_ID
left join GRP_BEN_PL_ID
on GRP_BEN_PL_ID.SUB_GROUP_KEY=BLK_1.SUB_GROUP_KEY
LEFT Join XXXX_ODS.INVOICE inv
on inv.BILL_TO_GROUP_KEY = BLK_1.GROUP_KEY
LEFT JOIN XXXX_ODS.INVOICE_BILLING_CATEGORY invbc
on invbc.INVOICE_KEY = inv.INVOICE_KEY
LEFT JOIN XXXX_ODS.INVOICE_LINE invl
on invl.INVOICE_BILLING_CATEGORY_KEY = invbc.INVOICE_BILLING_CATEGORY_KEY
GROUP BY
GRP_BEN_PL_ID.SUB_GROUP_KEY,
ACCT_NBR, --AS GROUPID,
SUB_GRP_ID,
DIVISION_ID
,GRP_BEN_PL_ID.HCC_BENEFIT_PLAN_ID
,INVOICE_NBR
,BUSTYPE
,GRP_BEN_PL_ID.FUNDING_TYPE,
,GRP_BEN_PL_ID.HCC_PROD_ID --AS PROCODE,
,PREMIUMTYPE
,INV.CURRENT_INVOICED_AMT
PREMIUMBILLED,
INV.CURRENT_INVOICED_AMT --AS PREMIUMDUEDATE,
,PREMIUMPAID
,PREMIUMAPPLYDATE
,MEMBERSXXXXL
ACCOUNT_TYPE
,STATE_CD,
GRP_BEN_PL_ID.SUB_COMPANY,
,LEVEL_NBR
order by ACCT_NBR,SUB_GRP_ID,LEVEL_NBR,DIVISION_ID
;
Thanks!
NEW ANSWER BASED ON COMMENT
Sorry I should have looked a bit closer I read the statement 'I get the error stating that it's not a GROUP BY statement' saw the count and made an assumption with my original answer.
With the further information provided in the comments I think the issue is actually that you are using the column alias in the group by.
When grouping you actually have to use the field names not the alias, if you have a static value (in this case '' AS MEMBERSXXXXL) you do not need to group by it SO
incorrect select using alias in the group by
select column1, column2 || column 3 as test2, '' as test, count(1) as cnt
from table
group by column1, test2, test
correct select omitting static value and putting full field in the group by
select column1, column2 || column 3 as test2, '' as test, count(1) as cnt
from table
group by column1, column2 || column 3
ORIGINAL ANSWER BELOW
where you have a count, min, max, sum ect within your select statement you need to tell it how to group the other columns....
you have
COUNT(invl.INVOICE_LINE_KEY) AS CONTRACTSXXXXL,
This means you will need a group by clause on your select.
Good resource for basics of this is
https://www.oracletutorial.com/oracle-basics/oracle-group-by/

Why sub SQL in FROM area can't be null?

select col_1,
col_2
from tbl_a A,
tbl_b B,
( select col_1,col_2 from tbl_c where clo_c_1 <> '1' ) C
where A.col_1 = B.col_1
and A.col_2 = B.col_2
and (A.col_2 = B.col_2
or C.col_2 = A.col_2);
My environment is Oracle,when I run this SQL,if the sub SQL C hasn't got a result,then the entire SQL returns NULL.Whereas if C has a result(not null) which fits other condions,there could be a result.Would somebody explain why sub SQL at the from area need to be not NULL?Thanks very much.
You need to bring yourself into the 90s and start using standard joins:
select col_1,
col_2
from tbl_a A
inner join
tbl_b B
on A.col_1 = B.col_1
and A.col_2 = B.col_2
left join
( select col_1,col_2 from tbl_c where clo_c_1 <> '1' ) C
on
C.col_2 = A.col_2
As a guess. I'm not entirely sure what your join conditions should be but that's my first attempt.
This is expected behaviour. When you join two result sets, you only want to get results where the join criteria is satisfied. If the criteria are not satisfied, you should get no results.
If I run the query "get me all the employees older than 65, and get their departments", if there are no employees older than 65, you would not expect to get any results, even if there are some departments in the database.
SELECT emp.name, dept.dept_name
FROM emp
JOIN dept
ON (emp.dept_no = dept.dept_no)
WHERE emp.age > 65;
As the others said, if you actually want to get rows regardless of whether the subquery has any results, you need to use an outer join.

Using an alias in a select statement in a join query

I am very new at using Oracle (in the class now). I have a problem with the query I am trying to run. I have researched a lot of other answers on this site and none of them seem to apply directly to my problem so the solutions aren't working.
I need to find the total amount spent on lunches by each employee.
Show first_name, last_name, credit_limit, and total_price_spent in your results.
Order the answer by total_price_spent in descending order. Only show the employees who spent more than their credit limit.
I figured out how to do everything but the part about showing only the employees who spent more than their credit limit. I tried to use a select statement at the end but discovered that I can't use an alias in a select statement so I don't really know where to go from here. Any help would be appreciated. This is what I have so far.
select a.first_name, a.last_name, credit_limit, sum(c.quantity * d.price) as total_price_spent
from l_employees a join l_lunches b on a.employee_id = b.employee_id join l_lunch_items c on b.lunch_id = c.lunch_id join l_foods d on c.supplier_id = d.supplier_id and c.product_code = d.product_code
group by a.first_name, a.last_name, a.credit_limit
order by total_price_spent desc;
As Mike said : Add HAVING
select a.first_name, a.last_name, credit_limit, sum(c.quantity * d.price) as total_price_spent
from l_employees a join l_lunches b on a.employee_id = b.employee_id join l_lunch_items c on b.lunch_id = c.lunch_id join l_foods d on c.supplier_id = d.supplier_id and c.product_code = d.product_code
group by a.first_name, a.last_name, a.credit_limit
having sum(c.quantity * d.price) > credit_limit
order by total_price_spent desc;
I think what you're looking for is a HAVING clause. It's like a WHERE, but is used when you're using group by. You want to drop it in between the group by and order by. Something like 'HAVING total > a.credit_limit' should work. If using the alias 'total' doesn't work (haven't tested this), you might have to do 'sum(c.quantity * d.price)' again in the HAVING clause instead of using total, so HAVING sum(c.quantity * d.price) > a.credit_limit.

How to use result of join in Linq

I have this SQL query and I want to use the same in Linq. I am confused as to how they use the group join alias in the main query?
SELECT '1st' AS POSITION , user as USR1, actiondate as ad1 , user2 as USR2, actiondate2 as ad2 ,user3 as USR3, actiondate3 as ad3, First as Co, * FROM APPLICATIONS A INNER JOIN
( SELECT MAX(ROW) AS MAXDATE ,APPLICATIONNO FROM FIRSTM
GROUP BY APPLICATIONNO) SULA1
ON A.APPLICATIONNO=SULA1.APPLICATIONNO
INNER JOIN FIRSTM FSTATUS
ON SULA1.APPLICATIONNO=FSTATUS.APPLICATIONNO AND
SULA1.MaxDate = FSTATUS.ROW
INNER JOIN APPLICATIONAPPLICANTS ON A.APPLICATIONNO
=APPLICATIONAPPLICANTS.APPLICATIONNO

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