Aggregate function in nested case statement requiring potentially messy group by - oracle

Pseudocode to describe what I'm looking at:
SELECT
COLUMN_A
, COLUMN_B
, CASE WHEN (OUTER_CONDITION_A = TRUE) THEN
CASE WHEN (INNER_CONDITION_1 = TRUE) THEN 'Choice 1'
WHEN (INNER_CONDITION_2 = TRUE) THEN 'Choice 2'
WHEN (INNER_CONDITION_3 = TRUE) THEN 'Choice 3'
ELSE 'Other Choice' END
ELSE CASE WHEN (OUTER_CONDITION_B = TRUE) THEN
CASE WHEN (INNER_CONDITION_4 = TRUE) THEN 'Choice 4'
WHEN (INNER_CONDITION_5 = TRUE) THEN 'Choice 5'
WHEN (INNER_CONDITION_6 = TRUE) THEN 'Choice 6'
ELSE TO_CHAR(MAX(DATE)) END
END AS 'COLUMN_C'
, COLUMN_D
FROM TABLE_A
Oracle SQL Developer is telling me that I need to add a GROUP BY clause:
GROUP BY
COLUMN_A
, COLUMN_B
, COLUMN_D
When I try to run this, I get an ORA-00979 (not a GROUP BY expression) error. I'm stumped here.

You are using an aggregate function MAX(DATE) in the case statement along with other columns without any group by clause.
Assuming, you want to get the overall max date in each row, you can use analytic MAX(DATE) OVER ():
SELECT
COLUMN_A
, COLUMN_B
, CASE WHEN (OUTER_CONDITION_A = TRUE) THEN
CASE WHEN (INNER_CONDITION_1 = TRUE) THEN 'Choice 1'
WHEN (INNER_CONDITION_2 = TRUE) THEN 'Choice 2'
WHEN (INNER_CONDITION_3 = TRUE) THEN 'Choice 3'
ELSE 'Other Choice' END
ELSE CASE WHEN (OUTER_CONDITION_B = TRUE) THEN
CASE WHEN (INNER_CONDITION_4 = TRUE) THEN 'Choice 4'
WHEN (INNER_CONDITION_5 = TRUE) THEN 'Choice 5'
WHEN (INNER_CONDITION_6 = TRUE) THEN 'Choice 6'
ELSE TO_CHAR(MAX(DATE) OVER ()) END
END AS 'COLUMN_C'
, COLUMN_D
FROM TABLE_A

Related

Missing keyword error in Case when in oracle

My select query before changes was:
select * from abc
WHERE
CASE WHEN NVL(gr.Rgid,a.pc) = 'CRA' THEN
CASE WHEN NVL(TRUNC(a.DATEOFSFROM),TO_DATE('99991231','YYYYMMDD')) >= TO_DATE('20170101','YYYYMMDD') THEN 'Y' ELSE 'N' END
When gr.Rgid='021SHOP' THEN
CASE WHEN TRUNC(a.datep) <= to_date('20190630', 'YYYYMMDD') then 'Y' ELSE 'N' end
ELSE 'Y' END = 'Y'
I need new case when statement,so I added:
select * from abc
WHERE
CASE WHEN NVL(gr.Rgid,a.pc) = 'CRA' THEN
CASE WHEN NVL(TRUNC(a.DATEOFSFROM),TO_DATE('99991231','YYYYMMDD')) >= TO_DATE('20170101','YYYYMMDD') THEN 'Y' ELSE 'N' END
When gr.Rgid='021SHOP' THEN
CASE WHEN TRUNC(a.datep) <= to_date('20190630', 'YYYYMMDD') then 'Y' ELSE 'N' end
ELSE 'Y' END = 'Y'
CASE WHEN NVL(gr.Rgid,a.pc) IN ('01FLW','002FE') then
a.datep <=to_date('20180131', 'YYYYMMDD') END;
I added these statement from my side
CASE WHEN NVL(gr.Rgid,a.pc) IN ('01FLW','002FE') then
a.datep <=to_date('20180131', 'YYYYMMDD') END;
But I am getting error:ORA-00905:missing keyword error. I searched these similar question but I only see is case when used is being wrong.But from my analysis,the case when I am using in right.
You didn't say what exactly should be the outcome so I guessed. Note comments within code, which contains new CASE:
SELECT *
FROM abc
WHERE CASE
WHEN NVL (gr.Rgid, a.pc) = 'CRA'
THEN
CASE
WHEN NVL (TRUNC (a.DATEOFSFROM),
TO_DATE ('99991231', 'YYYYMMDD')) >=
TO_DATE ('20170101', 'YYYYMMDD')
THEN
'Y'
ELSE
'N'
END
WHEN gr.Rgid = '021SHOP'
THEN
CASE
WHEN TRUNC (a.datep) <= TO_DATE ('20190630', 'YYYYMMDD')
THEN
'Y'
ELSE
'N'
END
-- your new WHEN begins here ...
WHEN NVL (gr.Rgid, a.pc) IN ('01FLW', '002FE')
THEN
CASE
WHEN a.datep <= TO_DATE ('20180131', 'YYYYMMDD')
THEN 'Y'
ELSE 'N'
END
-- ... and ends here
ELSE
'Y'
END =
'Y'
Your query:
select * from abc
WHERE
CASE WHEN NVL(gr.Rgid,a.pc) = 'CRA' THEN
CASE WHEN NVL(TRUNC(a.DATEOFSFROM),TO_DATE('99991231','YYYYMMDD')) >= TO_DATE('20170101','YYYYMMDD') THEN 'Y' ELSE 'N' END
When gr.Rgid='021SHOP' THEN
CASE WHEN TRUNC(a.datep) <= to_date('20190630', 'YYYYMMDD') then 'Y' ELSE 'N' end
ELSE 'Y' END = 'Y'
that's all ok.
When adding CASE WHEN NVL(gr.Rgid,a.pc) IN ('01FLW','002FE') then a.datep <=to_date('20180131', 'YYYYMMDD') END to the end you're screwing up the syntax.
Syntax: where a = b or c = d.
You wrote where a = b and then added c so it becomes where a = b c.
Add your new line with a AND or OR and get a value to compare it to, like
SELECT * FROM ABC
WHERE
CASE WHEN NVL(gr.Rgid,a.pc) = 'CRA' THEN
...
ELSE 'Y' END = 'Y'
-- new here
AND CASE WHEN NVL(gr.Rgid,a.pc) IN ('01FLW','002FE') AND a.datep <=to_date('20180131', 'YYYYMMDD')
then 'true'
ELSE 'false'
END = 'true';
I also transformed your case statement to a equation like a = b by moving your condition into the WHEN-Block and then comparing if it's the first when block or not by ... END = 'true'.
You cannot add where statements within a case expression like you did.
Please note that I wrote this without actual verification, so syntac errors may still occur.

SELECT with multiple JOINS Including LISTAGG with it's own JOIN

I have the following 2 queries that work perfectly when run separately.
QUERY 1
SELECT eps.PROPOSAL_NUMBER, eps.TITLE, per.FULL_NAME, ext.NRP_IREF_CD, ext.RESEARCH_TYPE_CD,
nsf.NSF_CODE, ext.NPS_THRUST_DESCRIPTION,
CASE
WHEN OPTION_1 = 'Y' THEN 'Option 1'
WHEN OPTION_2 = 'Y' THEN 'Option 2'
WHEN OPTION_3 = 'Y' THEN 'Option 3'
WHEN OPTION_4 = 'Y' THEN 'Option 4'
WHEN OPTION_5 = 'Y' THEN 'Option 5'
WHEN OPTION_6 = 'Y' THEN 'Option 6'
WHEN OPTION_7 = 'Y' THEN 'Option 7'
WHEN OPTION_8 = 'Y' THEN 'Option 8'
WHEN OPTION_9 = 'Y' THEN 'Option 9'
WHEN OPTION_0 = 'Y' THEN 'Not Applicable'
ELSE ''
END ONR,
abs.ABSTRACT_DETAILS
FROM EPS_PROPOSAL eps
LEFT JOIN EPS_PROPOSAL_EXT_T ext
ON eps.PROPOSAL_NUMBER = ext.PROPOSAL_NUMBER
LEFT JOIN EPS_PROP_PERSON per
ON eps.PROPOSAL_NUMBER = per.PROPOSAL_NUMBER AND
(per.PROP_PERSON_ROLE_ID = 'PI' OR per.PROP_PERSON_ROLE_ID = 'PD')
LEFT JOIN EPS_PROP_ABSTRACT abs
ON eps.PROPOSAL_NUMBER = abs.PROPOSAL_NUMBER
LEFT JOIN NSF_CODES nsf
ON eps.NSF_CODE = nsf.NSF_SEQUENCE_NUMBER
WHERE eps.OWNED_BY_UNIT = '401' AND eps.requested_start_date_initial >= DATE '2019-10-01';
Results
--------
PROPOSAL_NUMBER TITLE FULL_NAME NRP_IREF_CD ... <br />
2028 blah ... .... <br />
2029 blah2 ... .... <br />
2030 blah3 ... .... <br />
QUERY 2
SELECT eps.PROPOSAL_NUMBER,
LISTAGG(sk.DESCRIPTION, ', ') WITHIN GROUP (ORDER BY sk.DESCRIPTION) AS KEYWORDS
FROM EPS_PROPOSAL eps
LEFT JOIN EPS_PROP_SCIENCE_KEYWORD key
ON eps.PROPOSAL_NUMBER = key.PROPOSAL_NUMBER
LEFT JOIN SCIENCE_KEYWORD sk
ON key.SCIENCE_KEYWORD_CODE = sk.SCIENCE_KEYWORD_CODE
GROUP BY eps.PROPOSAL_NUMBER;
Results
--------
PROPOSAL_NUMBER KEYWORDS
2028 Keyword_A, Keyword_B, Keyword_C, Keyword_D
2029 Keyword_Y, Keyword_Z
2030 Keyword_W
So you can see that my main table that I'm dealing with is EPS_PROPOSAL and the PK there is PROPOSAL_NUMBER.
There are other tables that leverage that PK as a FK, like EPS_PROP_SCIENCE_KEYWORD, where you can have multiple rows of KEYWORDS that map to the same PROPOSAL_NUMBER. The problem is that only the ID or code is stored on that table, hence the need to JOIN with the SCIENCE_KEYWORD table to get at the description.
Question:
How do I combine these 2 queries so that my results will look like this:
Results
--------
PROPOSAL_NUMBER TITLE FULL_NAME NRP_IREF_CD ... KEYWORDS
2028 blah ... .... Keyword_A, Keyword_B, Keyword_C, Keyword_D
2029 blah2 ... .... Keyword_Y, Keyword_Z
2030 blah3 ... .... Keyword_W
The easiest way is to make small modification - to add OUTER APPLY with a subquery:
SELECT eps.PROPOSAL_NUMBER, eps.TITLE, per.FULL_NAME, ext.NRP_IREF_CD, ext.RESEARCH_TYPE_CD,
nsf.NSF_CODE, ext.NPS_THRUST_DESCRIPTION,
CASE
WHEN OPTION_1 = 'Y' THEN 'Option 1'
WHEN OPTION_2 = 'Y' THEN 'Option 2'
WHEN OPTION_3 = 'Y' THEN 'Option 3'
WHEN OPTION_4 = 'Y' THEN 'Option 4'
WHEN OPTION_5 = 'Y' THEN 'Option 5'
WHEN OPTION_6 = 'Y' THEN 'Option 6'
WHEN OPTION_7 = 'Y' THEN 'Option 7'
WHEN OPTION_8 = 'Y' THEN 'Option 8'
WHEN OPTION_9 = 'Y' THEN 'Option 9'
WHEN OPTION_0 = 'Y' THEN 'Not Applicable'
ELSE ''
END ONR,
abs.ABSTRACT_DETAILS,
k.keywords
FROM EPS_PROPOSAL eps
LEFT JOIN EPS_PROPOSAL_EXT_T ext
ON eps.PROPOSAL_NUMBER = ext.PROPOSAL_NUMBER
LEFT JOIN EPS_PROP_PERSON per
ON eps.PROPOSAL_NUMBER = per.PROPOSAL_NUMBER AND
(per.PROP_PERSON_ROLE_ID = 'PI' OR per.PROP_PERSON_ROLE_ID = 'PD')
LEFT JOIN EPS_PROP_ABSTRACT abs
ON eps.PROPOSAL_NUMBER = abs.PROPOSAL_NUMBER
LEFT JOIN NSF_CODES nsf
ON eps.NSF_CODE = nsf.NSF_SEQUENCE_NUMBER
OUTER APPLY(
SELECT
LISTAGG(sk.DESCRIPTION, ', ') WITHIN GROUP (ORDER BY sk.DESCRIPTION) AS KEYWORDS
FROM EPS_PROP_SCIENCE_KEYWORD key
LEFT JOIN SCIENCE_KEYWORD sk
ON key.SCIENCE_KEYWORD_CODE = sk.SCIENCE_KEYWORD_CODE
WHERE eps.PROPOSAL_NUMBER = key.PROPOSAL_NUMBER
) k
WHERE eps.OWNED_BY_UNIT = '401' AND eps.requested_start_date_initial >= DATE '2019-10-01';
One option would be using Common Table Expression :
WITH Q1 AS
(
SELECT eps.PROPOSAL_NUMBER, eps.TITLE, per.FULL_NAME, ext.NRP_IREF_CD, ext.RESEARCH_TYPE_CD,
nsf.NSF_CODE, ext.NPS_THRUST_DESCRIPTION,
CASE
WHEN OPTION_1 = 'Y' THEN 'Option 1'
WHEN OPTION_2 = 'Y' THEN 'Option 2'
WHEN OPTION_3 = 'Y' THEN 'Option 3'
WHEN OPTION_4 = 'Y' THEN 'Option 4'
WHEN OPTION_5 = 'Y' THEN 'Option 5'
WHEN OPTION_6 = 'Y' THEN 'Option 6'
WHEN OPTION_7 = 'Y' THEN 'Option 7'
WHEN OPTION_8 = 'Y' THEN 'Option 8'
WHEN OPTION_9 = 'Y' THEN 'Option 9'
WHEN OPTION_0 = 'Y' THEN 'Not Applicable'
ELSE ''
END ONR,
abs.ABSTRACT_DETAILS
FROM EPS_PROPOSAL eps
LEFT JOIN EPS_PROPOSAL_EXT_T ext
ON eps.PROPOSAL_NUMBER = ext.PROPOSAL_NUMBER
LEFT JOIN EPS_PROP_PERSON per
ON eps.PROPOSAL_NUMBER = per.PROPOSAL_NUMBER AND
(per.PROP_PERSON_ROLE_ID = 'PI' OR per.PROP_PERSON_ROLE_ID = 'PD')
LEFT JOIN EPS_PROP_ABSTRACT abs
ON eps.PROPOSAL_NUMBER = abs.PROPOSAL_NUMBER
LEFT JOIN NSF_CODES nsf
ON eps.NSF_CODE = nsf.NSF_SEQUENCE_NUMBER
WHERE eps.OWNED_BY_UNIT = '401' AND eps.requested_start_date_initial >= DATE'2019-10-01'
), Q2 AS
(
SELECT eps.PROPOSAL_NUMBER,
LISTAGG(sk.DESCRIPTION, ', ') WITHIN GROUP(ORDER BY sk.DESCRIPTION) AS KEYWORDS
FROM EPS_PROPOSAL eps
LEFT JOIN EPS_PROP_SCIENCE_KEYWORD key
ON eps.PROPOSAL_NUMBER = key.PROPOSAL_NUMBER
LEFT JOIN SCIENCE_KEYWORD sk
ON key.SCIENCE_KEYWORD_CODE = sk.SCIENCE_KEYWORD_CODE
GROUP BY eps.PROPOSAL_NUMBER
)
SELECT Q1.*, Q2.KEYWORDS
FROM Q1
JOIN Q2
ON Q2.PROPOSAL_NUMBER = Q1.PROPOSAL_NUMBER

ORA-01427 Single row subquery return more than one row

I have the below query once I run it, it's exceeded successfully without error, but when I run it inside a procedure, I got the single error.
CREATE OR REPLACE PROCEDURE ABLEA_NEW.AB_VATFILE
IS
fHandle UTL_FILE.FILE_TYPE;
err varchar2(200);
v_str VARCHAR2(4000);
CURSOR VAT1 IS
SELECT (SELECT cif_no
FROM nbfc_customer_m
WHERE customerid = a.bpid) ||
(SELECT EXTRACT_ACCT(HOST_ACCT_INFO, 'SUFFIX')
FROM LEA_AGREEMENT_GROUPGL_MAP A, FA_ACCTCATG_M B
WHERE EXTRACT_ACCT(A.HOST_ACCT_INFO, 'ACCTCATG') = B.ACCTCATG
AND B.GROUPID = 'FA'
AND A.ACTIVE_FLAG = 'Y'
and AGREEMENTID = a.caseid)
"Account No",lpad(a.caseid,6,0) Loan_No
,
(SELECT AGREEMENTNO
FROM lea_agreement_dtl
WHERE AGREEMENTID = a.caseid)
AGREEMENTNO
,
LPAD(A.productid,3,0) Scheme_ID,
(SELECT rpad(schemedesc,35,' ')
FROM lea_scheme_m
WHERE schemeid = a.productid)
SchemeDesc,
to_char(a.advicedate,'ddmmyyyy') advicedate,
it_conv(a.adviceamt) adviceamt,
rpad(a.chargeid,6,' ')chargeid,
(SELECT rpad(chargedesc,35,' ')
FROM nbfc_charges_m
WHERE chargeid = a.chargeid)
"Charge Description",
IT_CONV(a.chargeamt)chargeamt,
(SELECT
decode(count(1),0,'N','Y')
FROM nbfc_pmnt_dtl y
WHERE a.txnadviceid = y.txnadviceid
AND a.status = 'A'
AND y.status IS NULL
--and TRUNC(y.pmntdate) between :p_datefrom and :p_dateto
AND a.tax_applicable = 'Y'
AND a.ptxnadviceid IS NULL)Paid,
LPAD(b.chargeid,6,0)
"VAT ChargeID",
(SELECT RPAD(chargedesc,35,' ')
FROM nbfc_charges_m
WHERE chargeid = b.chargeid)
"VAT Charge Description",
IT_CONV(b.chargeamt)
"VAT Amount"
FROM (SELECT *
FROM nbfc_txn_advice_dtl
WHERE status = 'A' AND tax_applicable = 'Y' AND ptxnadviceid IS NULL)
a,
(SELECT *
FROM nbfc_txn_advice_dtl
WHERE status = 'A' AND ptxnadviceid IS NOT NULL) b
WHERE a.txnadviceid = b.ptxnadviceid;
BEGIN
fHandle := UTL_FILE.FOPEN('UAEDB', 'VAT', 'W');
FOR I IN VAT1
LOOP
v_str:= null;
v_str:= I."Account No"||I.Loan_No||I.AGREEMENTNO || I.Scheme_ID ||I.SchemeDesc|| I.advicedate|| I.adviceamt|| I.chargeid||I."Charge Description"||I.chargeamt||I.Paid||
I."VAT ChargeID" ||I."VAT Charge Description"||I."VAT Amount";
UTL_FILE.PUTF(fHandle,v_str);
UTL_FILE.PUTF(fHandle, '\n');
END LOOP;
UTL_FILE.FCLOSE(fHandle);
END ;
/
How can I solve this?
Note: the query return mor than 10000 record.
comment or un-comment the "(select from )as ColumnAlias" query column one by one, you can find which sub query column return more than one row

Select statement inside NVL

I'm trying to run the following query:
select a.*,
case when NVL (SELECT max(b.field1)
FROM b
where b.field2 = a.tbl_a_PK , 'TRUE') = 'TRUE'
then 'has no data in b'
else 'has data in b' end as b_status
from a
I checked and the select inside the nvl returns only 1 value (so there shouldn't be a problem there).
However I'm getting 'ORA-00936: missing expression'
NVL() requires 2 parameters: expression to test and default value e.g. nvl(some_field, 111). You just need to isolate query parameter by braces and provide second parameter like in this statement:
select nvl( (select 1 from dual), 34) from dual
In your variant parser expects comma after SELECT keyword and can't parse remaining string.
Exactly your statement must look like this:
select
a.*,
case when NVL(
( SELECT max(b.field1)
FROM b
where b.field2 = a.tbl_a_PK
),
'TRUE'
) = 'TRUE'
then 'has no data in b'
else 'has data in b' end as b_status
from a
Hope this helps ...
Update
In terms of performance is better to use exists rather then max :
select
a.*,
case when exists
( SELECT null
FROM b
where b.field2 = a.tbl_a_PK
and
b.field2 is not null
and
rownum = 1
),
then 'has data in b'
else 'has no data in b' end as b_status
from a
If you're searching for records in a which have/don't have associated records in b
select a.*,
case when b.field2 is null then 'has no data in b'
else 'has data in b'
as b_status
from a left outer join b
on a.tbl_a_PK = b.field2;
Should do it
the NVL(string1, replace_with) function requires 2 parameters, see docs here:
http://www.techonthenet.com/oracle/functions/nvl.php
Ora 10g docs: http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions105.htm
Since you know the problem, this query can fix it:
select a.*,
case
when (SELECT NVL(b.field2, 0) FROM b where b.field2 = a.tbl_a_PK and rownum = 1) > 0 then
'has data in b'
else
'has no data in b'
end b_status
from a
and runs faster.
You don't need max() to check if the value exists in another table, simply check if the primary key is not null.

Gettin error ORA-01732: data manipulation operation not legal on this view

Hi Gurus I am getting the error ORA-01732: data manipulation operation not legal on this view
when executing the below query
UPDATE (SELECT CR.AMOUNT AS AMOUNT,
CASE
WHEN MRG.AMOUNT_USD=0
THEN CR.AMOUNT
ELSE MRG.AMOUNT_USD
END AS AMOUNT_BILAT,
CR.ISUPDATED
FROM CRS_TT_BILAT_EXCL_MERGE1 MRG,CRS_T_CURRENT_RATES1 CR
WHERE SUBSTR(CR.DNIS_CD,1,3)=MRG.DNIS_CD
AND CR.PRODUCT_CUST_ID = MRG.PRODUCT_CUST_ID
AND CR.ISUPDATED <> 'Y'
AND ROWNUM = 1)
SET AMOUNT = AMOUNT_BILAT;
CR.ISUPDATED = 'Y';
I have simplified the above code from the below query
UPDATE CRS_T_CURRENT_RATES1 CR
SET CR.AMOUNT =
(SELECT
CASE
WHEN MRG.AMOUNT_USD=0
THEN CR.AMOUNT
ELSE MRG.AMOUNT_USD
END
FROM CRS_TT_BILAT_EXCL_MERGE1 MRG
WHERE SUBSTR(CR.DNIS_CD,1,3)=MRG.DNIS_CD
AND CR.PRODUCT_CUST_ID = MRG.PRODUCT_CUST_ID
AND ROWNUM = 1),
CR.ISUPDATED = 'Y'
WHERE EXISTS
(SELECT 1 FROM CRS_TT_BILAT_EXCL_MERGE1 MRG WHERE MRG.DNIS_CD = SUBSTR(CR.DNIS_CD, 1,3) AND CR.PRODUCT_CUST_ID = MRG.PRODUCT_CUST_ID )
AND
CR.ISUPDATED <> 'Y';
I was trying to optimize the 2nd query, since the second query uses two selects i was trying to replace that with a single query. Can any one please help me on this?
MERGE statement with selecting 1st row for each (AMOUNT_USD, DNIS_CD, PRODUCT_CUST_ID) - ROWNUM=1 condition from your query:
MERGE INTO CRS_T_CURRENT_RATES1 CR
USING (SELECT * FROM (
SELECT AMOUNT_USD,
DNIS_CD,
PRODUCT_CUST_ID
ROW_NUMBER() OVER (PARTITION BY AMOUNT_USD, DNIS_CD, PRODUCT_CUST_ID ORDER BY 1) AS ORD_NO
FROM CRS_TT_BILAT_EXCL_MERGE1
) WHERE ORD_NO = 1
) MGR
ON CR.PRODUCT_CUST_ID = MRG.PRODUCT_CUST_ID AND
SUBSTR(CR.DNIS_CD,1,3)=MRG.DNIS_CD
WHEN MATCHED THEN
UPDATE SET CR.AMOUNT = (CASE
WHEN MRG.AMOUNT_USD=0 THEN CR.AMOUNT
ELSE MRG.AMOUNT_USD
END),
ISUPDATED = 'Y'
WHERE ISUPDATED <> 'Y';
UPDATE: Using MERGE and ROWNUM won't work.
MERGE can help you avoid repeating SQL:
MERGE INTO CRS_T_CURRENT_RATES1 CR
USING
(
SELECT AMOUNT_USD, DNIS_CD, PRODUCT_CUST_ID
FROM CRS_TT_BILAT_EXCL_MERGE1
) MRG
ON
(
SUBSTR(CR.DNIS_CD,1,3) = MRG.DNIS_CD
AND CR.PRODUCT_CUST_ID = MRG.PRODUCT_CUST_ID
AND ROWNUM = 1
)
WHEN MATCHED THEN UPDATE SET
CR.ISUPDATED = 'Y',
CR.AMOUNT = CASE WHEN MRG.AMOUNT_USD=0 THEN CR.AMOUNT ELSE MRG.AMOUNT_USD END
Update
ROWNUM in the ON clause works on the updated table, not the data in the USING clause. The example below starts with two identical rows and only one gets updated:
create table test1(a number, b number);
insert into test1 values(1, 1);
insert into test1 values(1, 1);
merge into test1
using
(
select 1 a from dual
) test2
on (test1.a = test2.a and rownum = 1)
when matched then update set b = 0;
select * from test1;
A B
- -
1 0
1 1

Resources