Home > Software engineering >  How to write case expression inside merge statement to print the desired result
How to write case expression inside merge statement to print the desired result

Time:12-15

    CREATE TABLE DELIGATE_DETAILS_MAIN 
       (    E_ID NUMBER(10,0), 
        COMPLETED_DATE TIMESTAMP (6), 
         CONSTRAINT PK_DELIGATE_DETAILS_MAIN PRIMARY KEY (E_ID));

Insert into deligate_details_main (E_ID,COMPLETED_DATE) values (1,to_timestamp('13-12-21 6:05:23.991000000 PM','DD-MM-RR fmHH12:fmMI:SSXFF AM'));
Insert into deligate_details_main (E_ID,COMPLETED_DATE) values (2,to_timestamp('13-12-21 6:05:24.019000000 PM','DD-MM-RR fmHH12:fmMI:SSXFF AM'));
Insert into deligate_details_main (E_ID,COMPLETED_DATE) values (3,to_timestamp('13-12-21 6:05:24.029000000 PM','DD-MM-RR fmHH12:fmMI:SSXFF AM'));
Insert into deligate_details_main (E_ID,COMPLETED_DATE) values (4,to_timestamp('13-12-21 10:46:00.015000000 PM','DD-MM-RR fmHH12:fmMI:SSXFF AM'));

CREATE TABLE CONTROL_MAIN 
   (    E_ID NUMBER(10,0), 
    E_SPEC VARCHAR2(30 BYTE), 
     CONSTRAINT PK_CONTROL_MAIN PRIMARY KEY (E_ID));
     

Insert into CONTROL_MAIN (E_ID,E_SPEC) values (1,'SAP1');
Insert into CONTROL_MAIN (E_ID,E_SPEC) values (2,'FSAP');
Insert into CONTROL_MAIN (E_ID,E_SPEC) values (3,'SAP2');
Insert into CONTROL_MAIN (E_ID,E_SPEC) values (4,'SAP1-480');

CREATE TABLE QUESTION 
   (    E_ID NUMBER(10,0), 
    QUEST VARCHAR2(30 BYTE), 
     CONSTRAINT PK_QUESTION PRIMARY KEY (E_ID));
     

Insert into QUESTION (E_ID,QUEST) values (1,'Yes');
Insert into QUESTION (E_ID,QUEST) values (2,'No');
Insert into QUESTION (E_ID,QUEST) values (3,'Yes');
Insert into QUESTION (E_ID,QUEST) values (4,'Yes');

CREATE TABLE DELIGATE_DETAILS_TRANS 
   (    D_ID NUMBER(10,0), 
    E_ID NUMBER(10,0), 
    COMPLETED_DATE_TRANS DATE, 
    OWNER_DETAIL VARCHAR2(30 BYTE), 
     CONSTRAINT PK_DELIGATE_DETAILS_TRANS PRIMARY KEY (D_ID),
     CONSTRAINT FK_E_ID FOREIGN KEY (E_ID)
      REFERENCES TAM.DELIGATE_DETAILS_MAIN (E_ID));

Attempt:

MERGE INTO deligate_details_trans t USING ( SELECT
    ddm.e_id,
    ddm.completed_date
FROM
    deligate_details_main ddm
JOIN control_main cm ON ( cm.e_id = ddm.e_id AND cm.e_spec LIKE %'SAP'% )
    JOIN question      q ON ( q.e_id = ddm.e_id
                         AND q.quest = 'Yes' )
          ) s
    on (t.e_id = s.e_id)
    when not matched then
      insert (d_id,e_id, completed_date_trans, owner_detail)
      values (
    deligate_details_trans_sq.nextval,
    s.e_id,
    CAST(s.completed_date AS DATE),
--Here need to insert owner detail from control main
--If it is SAP1 or SAP2 then it will insert SAP1 or SAP2
--If it is SAP1-480 then it should insert SAP3);

Expected output:

 ------ --------- ----------------------- -------------- 
| D_ID | E_ID    | COMPLETED_DATE_TRANS  | OWNER_DETAIL |
 ------ --------- ----------------------- -------------- 
|    1 |       1 | 13-12-21              | SAP1         |
|    2 |       3 | 13-12-21              | SAP2         |
|    3 |       4 | 13-12-21              | SAP3         |
 ------ --------- ----------------------- -------------- 

For e_id 1: Based on the join condition from control_main and question table. Data should get inserted into the deligate_details_trans table and owner detail should be SAP1.

For e_id 2: Based on the join condition from control_main and question table. Data is NOT matching so it should not get inserted into the trans table.

For e_id 3: Based on the join condition from control_main and question table. Data should get inserted into the deligate_details_trans table and owner detail should be SAP2.

For e_id 4 it should check in the control main table and if it is SAP1-480 then it should insert SAP3 and for others, corresponding owner details should be inserted from the control_main table

CodePudding user response:

If you want the case expression in the insert's values clause then you need to expose the control table value in the using clause:

MERGE INTO deligate_details_trans t
USING (
    SELECT
        ddm.e_id,
        ddm.completed_date,
        cm.e_spec
    FROM
        deligate_details_main ddm
    JOIN control_main cm ON ( cm.e_id = ddm.e_id AND cm.e_spec LIKE '%SAP%' )
    JOIN question      q ON ( q.e_id = ddm.e_id
                         AND q.quest = 'Yes' )
) s
ON (t.e_id = s.e_id)
WHEN NOT MATCHED THEN INSERT (
    d_id,e_id, completed_date_trans, owner_detail
)
VALUES (
    deligate_details_trans_sq.nextval,
    s.e_id,
    CAST(s.completed_date AS DATE),
    CASE s.e_spec
        WHEN 'SAP1' THEN 'SAP1'
        WHEN 'SAP2' THEN 'SAP2'
        WHEN 'SAP1-480' THEN 'SAP3'
    END
);

Alternatively move the case expression into the using clause, give it an alias, and refer to that alias in the values clause:

MERGE INTO deligate_details_trans t
USING (
    SELECT
        ddm.e_id,
        ddm.completed_date,
        CASE cm.e_spec
            WHEN 'SAP1' THEN 'SAP1'
            WHEN 'SAP2' THEN 'SAP2'
            WHEN 'SAP1-480' THEN 'SAP3'
        END AS owner_detail
    FROM
        deligate_details_main ddm
    JOIN control_main cm ON ( cm.e_id = ddm.e_id AND cm.e_spec LIKE '%SAP%' )
    JOIN question      q ON ( q.e_id = ddm.e_id
                         AND q.quest = 'Yes' )
) s
ON (t.e_id = s.e_id)
WHEN NOT MATCHED THEN INSERT (
    d_id,e_id, completed_date_trans, owner_detail
)
VALUES (
    deligate_details_trans_sq.nextval,
    s.e_id,
    CAST(s.completed_date AS DATE),
    s.owner_detail
);

db<>fiddle showing both (with %'SAP'% changed to '%SAP%', and sequence creation added).


I'm not sure why you have a timestamp in one table and a date in the other, and you don't need an explicit cast (though it doesn't hurt). But if you're doing that because you're only interested in the date part you should be aware that an Oracle date still has a time component, even if it isn't being shown in your DD-MM-YY format or db<>fiddle's default DD-MON-YY format. If you want to 'lose' the time part you can truncate the value at the day (DD) component, shown in this db<>fiddle which changes the display format so you can see the difference. But you might want to keep the time - in which case, ignore this part...

  • Related