Есть ли способ включить CASE WHEN или NVL в СЛИЯНИЕ oracle sql?

#sql #oracle #merge #nvl

#sql #Oracle #слияние #nvl

Вопрос:

У меня есть инструкция слияния ниже, и я хочу добавить в качестве условия, что если X_RECEIVED_ON_DT равно нулю, он будет использовать дату в FULFILLED_ON_DT и PO_CLOSED_DT, которые являются столбцами в TGT (целевой таблице) для заполнения столбца TGT.X_GAAP_EXCH_RATE_WID

  MERGE
/*  PARALLEL(8) */
INTO W_PURCH_COST_F TGT USING
(SELECT
  /*  PARALLEL(8) */
  cost.INTEGRATION_ID,
  cost.X_RECEIVED_ON_DT,
  cost.LOC_CURR_CODE,
  COALESCE(gaap.ROW_WID,0) X_GAAP_EXCH_RATE_WID
FROM W_Purch_Cost_F_3955 cost
JOIN W_DAY_D wday
ON TRUNC(cost.X_RECEIVED_ON_DT)=TRUNC(wday.CALENDAR_DATE)
LEFT OUTER JOIN WC_GAAP_EXCH_RATE_G gaap
ON gaap.PERIOD               =wday.PER_NAME_ENT_PERIOD
AND cost.LOC_CURR_CODE       =gaap.FROM_CURCY_CD
) SRC ON (TGT.INTEGRATION_ID = SRC.INTEGRATION_ID AND TGT.DATASOURCE_NUM_ID = 310)
WHEN MATCHED THEN
  UPDATE SET TGT.X_GAAP_EXCH_RATE_WID = SRC.X_GAAP_EXCH_RATE_WID;
  

Ответ №1:

Если вы хотите ссылаться на W_PURCH_COST_F (псевдоним TGT ) в исходном запросе, вам придется включить его в предложение SRC ‘s FROM .

Это означает, что в этом W_PURCH_COST_F заявлении у вас будет две MERGE таблицы — одна в качестве цели слияния (как у вас уже есть сейчас), другая в качестве «источника», используемого для объединения с другими таблицами в SRC . Тогда использовать NVL , CASE или DECODE и делать то, что вы хотите, — простая задача.

Хотя я не совсем понимаю, как вы будете использовать оба FULFILLED_ON_DT и PO_CLOSED_DT , но я надеюсь, что вы знаете.


Пример, основанный на схеме Скотта (поскольку у меня нет ваших таблиц):

Это не сработает — вы не можете ссылаться TGT в SRC :

 SQL> merge into emp e
  2  using (select distinct d.deptno, d.dname, d.loc
  3         from dept d
  4         where d.deptno = e.deptno                --> not allowed
  5        ) x
  6  on (e.deptno = x.deptno)
  7  when matched then update set e.ename = x.loc;
       where d.deptno = e.deptno
                        *
ERROR at line 4:
ORA-00904: "E"."DEPTNO": invalid identifier
  

Но, если используется в SRC предложении FROM , это работает:

 SQL> merge into emp e
  2  using (select distinct d.deptno, d.dname, d.loc
  3         from dept d join emp a on a.deptno = d.deptno
  4        ) x
  5  on (e.deptno = x.deptno)
  6  when matched then update set e.ename = x.loc;

14 rows merged.

SQL>
  

Варианты, которые вы, возможно, захотите рассмотреть, следующие:

  • Вложенный NVL : nvl(x_received_on_dt, nvl(fulfilled_on_dt, po_closed_dt))

  • coalesce (возвращает первое ненулевое значение):

     coalesce(x_received_on_dt, fulfilled_on_dt, po_closed_dt, sysdate) 
      

coalesce для меня это лучший выбор.

Комментарии:

1. Привет @Littlefoot , извините, он будет использовать либо FULFILLED_ON_DT, либо PO_CLOSED_DT, если значение FULFILLED_ON_DT не равно null, он будет использовать это, если его значение равно null, будет использовать PO_CLOSED_DT, иначе 0

2. Хорошо, используйте вложенные NVL. Однако вы не можете использовать 0 (число) со значениями ДАТЫ из-за несовместимых типов данных. Должно быть что-то еще — значение ДАТЫ (например, SYSDATE или какая-либо недопустимая дата, например, ДАТА ‘1000-01-01’).

3. Привет @ Littlefoot, я получил ошибку с отсутствующим ключевым словом. это мой выбор NVL (СЛУЧАЙ, КОГДА стоимость. X_RECEIVED_ON_DT РАВНО НУЛЮ, ТОГДА SRC1.FULFILLED_ON_DT, ИНАЧЕ SRC1.PO_CLOSED_DT,0)

4. Я отредактировал свой ответ и добавил примеры NVL и COALESCE; взгляните.