【问题标题】:How to write case expression inside merge statement to print the desired result如何在合并语句中编写 case 表达式以打印所需的结果
【发布时间】:2022-01-17 23:44: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));

尝试:

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 和问题表的连接条件。数据应插入到 deligate_details_trans 表中,所有者详细信息应为 SAP1。

对于 e_id 2:基于 control_main 和问题表的连接条件。数据不匹配,因此不应插入到 trans 表中。

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

对于e_id 4,它应该检查控制主表,如果它是SAP1-480,那么它应该插入SAP3,对于其他人,应该从control_main表中插入相应的所有者详细信息

【问题讨论】:

    标签: sql oracle case sql-merge


    【解决方案1】:

    如果您想要插入的values 子句中的case 表达式,那么您需要在using 子句中公开控制表值:

    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%',并添加了序列创建)。


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

    【讨论】:

    • 感谢它对我有用。我看到您已经编辑了问题并删除了错误对齐的虚拟表。我可以知道如何在提问时从senseful.github.io/text-table 粘贴虚拟表吗?
    • @Vicky - 我把它改成了 Markdown 表;但是可以通过将您的版本封闭在代码围栏中来保持您的版本不受 Senseful 影响 - 只需在表格前后的一行中放置三个反引号 ```,然后将其视为代码并以等宽字体显示并对齐。 (您现在可以/应该对实际代码执行此操作,而不是将所有内容缩进四个字符...)我已更新问题以显示您的原始版本,以便您了解我的意思。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-01-11
    • 1970-01-01
    • 2010-10-19
    • 2011-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多