Issue With GROUP BY In Query - oracle
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/
Related
Error when running a sub query in Oracle SQL
I am trying to join three tables using a sub query. The result of the first left outer join is to be used with another table to get a composite view with all attributes. I am getting an error where the compile says, Unknown Command for the table in the second join clause. When I create two independent views and then join then it works fine. (select l.ENROLLED_CONTENT, l.LEARNING_ENROLLMENT_LEARNER, l.EMPLOYEE_ID, l.JOB_FAMILY_GROUP, l.EMPLOYEE_TYPE, l.JOB_FAMILY, l.LEARNING_ENROLLMENT, l.COMPLETION_STATUS, l.COMPLETION_DATE, l.EXPIRATION_DATE, l.CF_LRV_LEARNING_CONTENT_NUMBER, l.LEARNING_CONTENT_DETAIL, l.LEARNING_CONTENT_TYPE, l.LESSON_TYPE, e.id# "WK_WORKER_ID" from tgt_workday.learning l left outer join ods_hrmaster.employee e on l.EMPLOYEE_ID = e.employee#) t1 left outer join ( select per_ids_id, per_id, id_pureid from ods_pure.person_ids ) t2 on t1.wk_worker_id = t2.value where t2.type = 'Employee ID';
You can write it in a simple way. There is no need to make sub-queries as: SELECT L.ENROLLED_CONTENT, L.LEARNING_ENROLLMENT_LEARNER, L.EMPLOYEE_ID, L.JOB_FAMILY_GROUP, L.EMPLOYEE_TYPE, L.JOB_FAMILY, L.LEARNING_ENROLLMENT, L.COMPLETION_STATUS, L.COMPLETION_DATE, L.EXPIRATION_DATE, L.CF_LRV_LEARNING_CONTENT_NUMBER, L.LEARNING_CONTENT_DETAIL, L.LEARNING_CONTENT_TYPE, L.LESSON_TYPE, E.ID# "WK_WORKER_ID" FROM TGT_WORKDAY.LEARNING L LEFT OUTER JOIN ODS_HRMASTER.EMPLOYEE E ON L.EMPLOYEE_ID = E.EMPLOYEE# LEFT OUTER JOIN ODS_PURE.PERSON_IDS T2 ON E.ID# = T2.VALUE AND T2.TYPE = 'Employee ID'; Once you use the outer joined table's column in WHERE clause, It will result in the same result as inner join(there is another ways to use it in WHERE clause though). So it is better to avoid using outer joined table's column in the WHERE clause.
Try as SELECT * FROM ( (SELECT l.ENROLLED_CONTENT, l.LEARNING_ENROLLMENT_LEARNER, l.EMPLOYEE_ID, l.JOB_FAMILY_GROUP, l.EMPLOYEE_TYPE, l.JOB_FAMILY, l.LEARNING_ENROLLMENT, l.COMPLETION_STATUS, l.COMPLETION_DATE, l.EXPIRATION_DATE, l.CF_LRV_LEARNING_CONTENT_NUMBER, l.LEARNING_CONTENT_DETAIL, l.LEARNING_CONTENT_TYPE, l.LESSON_TYPE, e.id# "WK_WORKER_ID" FROM tgt_workday.learning l LEFT OUTER JOIN ods_hrmaster.employee e ON l.EMPLOYEE_ID = e.employee) t1 LEFT OUTER JOIN (SELECT per_ids_id, per_id, id_pureid FROM ods_pure.person_ids) t2 ON t1.wk_worker_id = t2.VAL AND t2.TYPE = 'Employee ID')
Column name is not passed to PostgreSQL on JDBC Scan in Apache Drill
While trying to run SQL query for PostgreSQL, instead of the column names from the table referred it it pushing down * to the database. select m.m_id, cnt_c_no from ( select m_id from pg_test_main.test1.table1 where last_date >= '2019-01-01 00:00:00' ) as m left join ( select ci.m_id, count(ci.c_no) as cnt_c_no from ( select m_id, c_no from pg_test.public.table2 ) as ci inner join ( select c_no from pg_test.public.table3 where is_del = 'F' ) as c on ci.c_no = c.c_no group by ci.m_id ) as join1 on m.m_id = join1.m_id; 00-00 Screen 00-01 Project(m_id=[$0], cnt_c_no=[$1]) 00-02 Project(m_id=[$0], cnt_c_no=[$2]) 00-03 HashJoin(condition=[=($0, $1)], joinType=[left], semi-join: =[false]) 00-05 Jdbc(sql=[SELECT "m_id" FROM "test1"."table1" WHERE "last_date" >= '2019-01-01 00:00:00' ]) 00-04 Project(m_id0=[$0], cnt_c_no=[$1]) 00-06 HashAgg(group=[{0}], cnt_c_no=[COUNT($1)]) 00-07 Project(m_id=[$0], c_no=[$1]) 00-08 HashJoin(condition=[=($1, $2)], joinType=[inner], semi-join: =[false]) 00-10 Project(m_id=[$3], c_no=[$1]) 00-12 Jdbc(sql=[SELECT * FROM "public"."table2" ]) 00-09 Project(c_no0=[$0]) 00-11 Project(c_no=[$0]) 00-13 SelectionVectorRemover 00-14 Filter(condition=[=($60, 'F')]) 00-15 Jdbc(sql=[SELECT * FROM "public"."table3" ]) As you can see, Jdbc Scan for table1 was using column names. but, Jdbc Scan for table2 and table3 was not using column names. It pushed down * to the database. How can I control jdbc scan so that it can push down colume names? Apache Drill version is 1.16.0 (embedded-mode)
I tried to reproduce it with MySQL on both Drill 1.17 and Drill 1.15, but for the query, similar to the query you have specified, all the query is pushed into the JDBC storage: SELECT m.person_id, cnt_c_no FROM (SELECT person_id FROM mysql.`drill_mysql_test1`.person1 WHERE date_field >= '2019-01-01 00:00:00') AS m LEFT JOIN (SELECT ci.person_id, count(ci.last_name) AS cnt_c_no FROM (SELECT person_id, last_name FROM mysql.`drill_mysql_test`.person) AS ci INNER JOIN (SELECT last_name FROM mysql.`drill_mysql_test`.person2 WHERE boolean_field = 'F' ) AS c ON ci.last_name = c.last_name GROUP BY ci.person_id) AS join1 ON m.person_id = join1.person_id The plan for this query: 00-00 Screen 00-01 Project(person_id=[$0], cnt_c_no=[$1]) 00-02 Jdbc(sql=[SELECT `t0`.`person_id`, `t5`.`cnt_c_no` FROM (SELECT `person_id` FROM `drill_mysql_test1`.`person1` WHERE `date_field` >= '2019-01-01 00:00:00') AS `t0` LEFT JOIN (SELECT `t1`.`person_id`, COUNT(`t1`.`last_name`) AS `cnt_c_no` FROM (SELECT `person_id`, `last_name` FROM `drill_mysql_test`.`person`) AS `t1` INNER JOIN (SELECT `last_name` FROM `drill_mysql_test`.`person2` WHERE `boolean_field` = 'F') AS `t3` ON `t1`.`last_name` = `t3`.`last_name` GROUP BY `t1`.`person_id`) AS `t5` ON `t0`.`person_id` = `t5`.`person_id` ]) Could you please provide CTAS for Postgres tables, so I will try to reproduce it again with specific data types. Also, if possible, please check whether this issue is still reproduced on Drill 1.17. UPD: Comment under this answer helped to discover that this problem was caused by the following issue: https://issues.apache.org/jira/browse/DRILL-7340 and it will be resolved in Drill 1.18.0.
Only want to return rows that have duplicate unitid within group by unitid
I am working in SSRS querying against an oracle database. So I have a data source and this report is supposed to find duplicate Work Orders based on multiple open workorders on a unique unitid. So I only want to show groups that have more then one entry as they are grouped by unitid. SELECT COMPSTSB.UNITID, COMPSTSB.UNITTYPE, ACTDEFN.ACTDESC, ACTDEFN.ACTCODE, HISTORY.WONO, HISTORY.COMPFLAG, HISTORY.ADDDTTM, HISTORY.COMMENTS FROM (IMSV7.COMPSTSB COMPSTSB INNER JOIN IMSV7.HISTORY HISTORY ON COMPSTSB.COMPKEY=HISTORY.COMPKEY) INNER JOIN IMSV7.ACTDEFN ACTDEFN ON HISTORY.ACTKEY=ACTDEFN.ACTKEY WHERE HISTORY.COMPFLAG='Y' AND NOT (ACTDEFN.ACTCODE='DBR' OR ACTDEFN.ACTCODE='IN') ORDER BY COMPSTSB.UNITTYPE, COMPSTSB.UNITID, HISTORY.ADDDTTM Can anyone point me in the right direction? And yes before someone says this has been asked a million times, I did search. Point me to the million times and I will see if I feel they match my question. Ideally in the SQL I could make new column that returned a count of the unitid and I did attempt this but failed, and then I could filter on that column to remove any that only had one count. I really don't think this should be difficult but I have spent about 4 hours on it so far. Thanks in advance! Steven
If I understood your question right, the following should give you what's needed : SELECT * FROM ( SELECT COMPSTSB.UNITID, COMPSTSB.UNITTYPE, ACTDEFN.ACTDESC, ACTDEFN.ACTCODE, HISTORY.WONO, HISTORY.COMPFLAG, HISTORY.ADDDTTM, HISTORY.COMMENTS, COUNT(1) OVER (PARTITION BY COMPSTSB.UNITID) AS numDups FROM (IMSV7.COMPSTSB COMPSTSB INNER JOIN IMSV7.HISTORY HISTORY ON COMPSTSB.COMPKEY=HISTORY.COMPKEY) INNER JOIN IMSV7.ACTDEFN ACTDEFN ON HISTORY.ACTKEY=ACTDEFN.ACTKEY WHERE HISTORY.COMPFLAG='Y' AND NOT (ACTDEFN.ACTCODE='DBR' OR ACTDEFN.ACTCODE='IN') )a WHERE a.numDups >1 ORDER BY COMPSTSB.UNITTYPE, COMPSTSB.UNITID, HISTORY.ADDDTTM
I expect you are concerned about having duplicate values of UNITID in the IMSV7.COMPSTSB table. If so adding this join to your query should enable ou to identify them: JOIN (SELECT COMPSTSB.UNITID FROM IMSV7.COMPSTSB GROUP BY COMPSTSB.UNITID HAVING COUNT(COMPSTSB.UNITID) > 1) dups ON DUPS.UNITID = COMPSTSB.UNITID JOIN IMSV7.HISTORY HISTORY Here's the full query: SELECT COMPSTSB.UNITID , COMPSTSB.UNITTYPE , ACTDEFN.ACTDESC , ACTDEFN.ACTCODE , HISTORY.WONO , HISTORY.COMPFLAG , HISTORY.ADDDTTM , HISTORY.COMMENTS FROM IMSV7.COMPSTSB COMPSTSB JOIN (SELECT COMPSTSB.UNITID FROM IMSV7.COMPSTSB GROUP BY COMPSTSB.UNITID HAVING COUNT(COMPSTSB.UNITID) > 1) dups ON DUPS.UNITID = COMPSTSB.UNITID JOIN IMSV7.HISTORY HISTORY ON COMPSTSB.COMPKEY = HISTORY.COMPKEY JOIN IMSV7.ACTDEFN ACTDEFN ON HISTORY.ACTKEY = ACTDEFN.ACTKEY WHERE HISTORY.COMPFLAG = 'Y' AND ACTDEFN.ACTCODE NOT IN ('DBR','IN') ORDER BY COMPSTSB.UNITTYPE , COMPSTSB.UNITID , HISTORY.ADDDTTM; Since the above query didn't work you can try outer joins to similar sub queries on each of your tables and limit to only records where the outer joined table returns data. This will show you which tables in your query are cuasing your extra rows.: SELECT COMPSTSB.UNITID , COMPSTSB.UNITTYPE , ACTDEFN.ACTDESC , ACTDEFN.ACTCODE , HISTORY.WONO , HISTORY.COMPFLAG , HISTORY.ADDDTTM , HISTORY.COMMENTS , DUPS.UNITID UNITID_DUP , DUPS2.COMPKEY COMPKEY_DUP , DUPS3.ACTKEY ACTKEY_DUP FROM IMSV7.COMPSTSB COMPSTSB JOIN IMSV7.HISTORY HISTORY ON COMPSTSB.COMPKEY = HISTORY.COMPKEY JOIN IMSV7.ACTDEFN ACTDEFN ON HISTORY.ACTKEY = ACTDEFN.ACTKEY LEFT JOIN (SELECT COMPSTSB.UNITID FROM IMSV7.COMPSTSB GROUP BY COMPSTSB.UNITID HAVING COUNT(COMPSTSB.UNITID) > 1) dups ON DUPS.UNITID = COMPSTSB.UNITID LEFT JOIN (SELECT HISTORY.COMPKEY FROM IMSV7.HISTORY GROUP BY HISTORY.COMPKEY HAVING COUNT(HISTORY.COMPKEY) > 1) dups2 ON DUPS.UNITID = COMPSTSB.UNITID LEFT JOIN (SELECT ACTDEFN.ACTKEY FROM IMSV7.ACTDEFN GROUP BY ACTDEFN.ACTKEY HAVING COUNT(ACTDEFN.ACTKEY) > 1) dups3 ON DUPS.UNITID = COMPSTSB.UNITID WHERE HISTORY.COMPFLAG = 'Y' AND ACTDEFN.ACTCODE NOT IN ('DBR','IN') AND ( DUPS.UNITID IS NOT NULL OR DUPS2.COMPKEY IS NOT NULL OR DUPS3.ACTKEY IS NOT NULL) ORDER BY COMPSTSB.UNITTYPE , COMPSTSB.UNITID , HISTORY.ADDDTTM;
Assistance replacing oracle (+) joins to ANSI joins
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;
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".