如何在 merge 语句中编写 case 表达式以打印所需的结果

How to write case expression inside merge statement to print the desired result

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

尝试:

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

预期输出:

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

对于 e_id 1:基于来自 control_main 和问题 table 的连接条件。数据应插入 deligate_details_trans table 并且所有者详细信息应为 SAP1。

对于 e_id 2:基于来自 control_main 和问题 table 的连接条件。数据不匹配,因此不应将其插入到 trans table.

对于 e_id 3:基于 control_main 和问题 table 的连接条件。数据应插入 deligate_details_trans table 并且所有者详细信息应为 SAP2。

对于 e_id 4,它应该检查主控件 table,如果它是 SAP1-480,那么它应该插入 SAP3,对于其他的,应该从 control_maintable

如果您想在插入的 values 子句中使用 case 表达式,则需要在 using 子句中公开控件 table 值:

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

或者将 case 表达式移动到 using 子句中,给它一个别名,并在 values 子句中引用该别名:

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 显示两者(%'SAP'% 更改为 '%SAP%',并添加了序列创建)。


我不确定为什么一个 table 中有时间戳而另一个中有日期,而且您不需要显式强制转换(尽管它没有坏处)。但是 if 你这样做是因为你只对日期部分感兴趣 你应该知道 Oracle 日期仍然有一个时间部分,即使它没有显示在您的 DD-MM-YY 格式或 db<>fiddle 的默认 DD-MON-YY 格式。如果您想要 'lose' 时间部分,您可以截断日期 (DD) 部分的值,shown in this db<>fiddle 这会更改显示格式,以便您可以看到差异。但你可能想保留时间 - 在这种情况下,请忽略这部分...