Заполнить столбец на основе условного приоритета в Teradata

Мне нужно заполнить столбец на основе условного приоритета:

Если O_M не равен нулю (например: 0.34), я проверяю Prev. record (который упорядочивается TP_N) в том же столбце O_M, и если он равен нулю для 3 или более экземпляров, закодированных кодами (OD03,OT03,MO03), тогда я должен заполнить столбец To_Compute текущим O_M значение - 0.34. Мне нужно повторить это для каждого раздела (DT,MNTH,P_ID,A_BR,D_BR,B_BR,DR), упорядоченного по TP_N. Я должен искать эти коды только в столбцах O_N - (OD03,OT03,MO03)

DT        MNTH  P_ID    A_BR    D_BR B_BR   TP_N    DR  O_M O_N  TO_Compute
9/29/2016   9   QT21    1506    05Y XS-123  487,006 0   0   ?       0
9/29/2016   9   QT21    1506    05Y XS-123  487,007 0   0   OD03    0
9/29/2016   9   QT21    1506    05Y XS-123  487,008 0   0   OD03    0
9/29/2016   9   QT21    1506    05Y XS-123  487,009 0   0   OD03    0
9/29/2016   9   QT21    1506    05Y XS-123  487,010 0   0   OD03    0
9/29/2016   9   QT21    1506    05Y XS-123  487,011 0   0   OD03    0
9/29/2016   9   QT21    1506    05Y XS-123  487,012 0   0   OD03    0
9/29/2016   9   QT21    1506    05Y XS-123  487,013 0   0   OD03    0
9/29/2016   9   QT21    1506    05Y XS-123  487,014 0   0   MO03    0
9/29/2016   9   QT21    1506    05Y XS-123  487,015 0   0   OT03    0
9/29/2016   9   QT21    1506    05Y XS-123  487,016 0   0   OD03    0
9/29/2016   9   QT21    1506    05Y XS-123  487,017 0   0.34    ?   0.34
9/29/2016   9   QT21    1506    05Y XS-123  487,018 0   0   OD03    0
9/29/2016   9   QT21    1506    05Y XS-123  487,019 0   1.03    ?   0
9/29/2016   9   QT21    1506    05Y XS-123  487,020 0   0.3     ?   0
9/29/2016   9   QT21    1506    05Y XS-123  487,021 0   1.25    ?   0
9/29/2016   9   QT21    1506    05Y XS-123  487,022 0   0   OP04    0
9/29/2016   9   QT21    1506    05Y XS-123  487,023 0   10.53   ?   0
9/29/2016   9   QT21    1506    05Y XS-123  487,024 0   0.37    ?   0
9/29/2016   9   QT21    1506    05Y XS-123  487,025 0   0.28    ?   0
9/29/2016   9   QT21    1506    05Y XS-123  487,026 0   0   OD03    0
9/29/2016   9   QT21    1506    05Y XS-123  487,027 0   0   OD03    0
9/29/2016   9   QT21    1506    05Y XS-123  487,028 0   0.6     ?   0
9/29/2016   9   QT21    1506    05Y XS-123  487,029 0   0.38    ?   0
9/29/2016   9   QT21    1506    05Y XS-123  487,030 0   0.4 ?   0
9/29/2016   9   QT21    1506    05Y XS-123  487,031 0   0.35    ?   0
9/29/2016   9   QT21    1506    05Y XS-123  487,032 0   0.45    ?   0
9/29/2016   9   QT21    1506    05Y XS-123  487,033 0   0   OD03    0
9/29/2016   9   QT21    1506    05Y XS-123  487,034 0   0   OD03    0
9/29/2016   9   QT21    1506    05Y XS-123  487,035 0   0   OD03    0
9/29/2016   9   QT21    1506    05Y XS-123  487,036 0   0.3     ?   0.3
9/29/2016   9   QT21    1506    05Y XS-123  487,037 0   0.35    ?   0
9/29/2016   9   QT21    1506    05Y XS-123  487,038 0   0.52    ?   0

Однако, если O_M не равно нулю (например: 0.6 - 11-я строка снизу для столбца O_M), я проверяю Prev. record в том же столбце O_M, и у меня есть только 2 предыдущие записи как zero (для 3 или более экземпляров, закодированных кодами (OD03,OT03,MO03), тогда я должен заполнить столбец To_Compute значением 0.

Если O_M не равно нулю (например: 0.3 Третья последняя строка для O_M), я проверяю Prev. record в том же столбце O_M, и здесь он равен нулю для 3 или более экземпляров, закодированных кодами (OD03,OD03,OD03), тогда я должен заполнить столбец To_Compute текущим значением O_M - 0.3.

Я новичок в ТД. Любой свет на это может помочь.


person Prasanna Nandakumar    schedule 29.10.2018    source источник
comment
Должны ли коды в столбце O_N быть в каком-то конкретном порядке и должны ли присутствовать все три?   -  person M. Wise    schedule 29.10.2018
comment
Если 3 и более пред. последовательная запись равна нулю, затем я проверяю столбец O_N, и он должен соответствовать этим трем кодам. (без нулей). Без особого порядка.   -  person Prasanna Nandakumar    schedule 29.10.2018


Ответы (2)


Не проверено, но это должно работать на основе вашего описания:

case
   when sum(O_M) -- previous three rows are all 0 (assuming no negative values exist)
        over (partition by ??
              order by TP_N
              rows between 3 preceding and 1 preceding) = 0
    and -- prvious three rows contain any of the searched codes
        sum(case when O_N IN ('OD03','OT03','MO03') then 1 else 0 end)
        over (partition by ??
              order by TP_N
              rows between 3 preceding and 1 preceding) = 3
   then O_M
   else 0
end
person dnoeth    schedule 29.10.2018
comment
Исходя из моего опыта, вы не можете использовать оконную функцию в части when оператора case, но вы можете использовать ее в части then. - person M. Wise; 30.10.2018
comment
@M.Wise: Когда вы можете использовать его в ТОГДА, вы также можете использовать его в КОГДА или ЕЩЕ :-) - person dnoeth; 30.10.2018
comment
Я подтвердил это вчера. Вы получаете ошибку «Незаконное использование случая» в КОГДА, в то время как в ТОГДА все работает нормально. - person M. Wise; 30.10.2018
comment
@M.Wise: Ну, я делаю это все время, это должно быть что-то еще. Можете ли вы поделиться неудачной частью? - person dnoeth; 30.10.2018
comment
@dnoeth работает отлично. Я проверяю сценарии. однако для заданного вопроса - я получил ожидаемый результат - person Prasanna Nandakumar; 31.10.2018

Я предложу вам два возможных решения, чтобы вы могли решить, какое из них лучше всего подходит для вашей ситуации. Первый проще, но более утомительный, поскольку он просто соединяется с одной и той же таблицей 3 раза. Предположим, что указанные выше данные существуют в таблице DATASET:

select ds1.dt
,ds1.mnth
,ds1.p_id
,ds1.a_br
,ds1.d_br
,ds1.b_br
,ds1.tp_n
,ds1.dr
,ds1.o_m
,ds1.o_n
,case when zeroifnull(ds4.o_m) + zeroifnull(ds3.o_m) + zeroifnull(ds2.o_m) = 0 and ds4.o_n in ('OD03','OT03','MO03') and ds3.o_n in ('OD03','OT03','MO03') and ds2.o_n in ('OD03','OT03','MO03') then ds1.o_m
else 0 end as TO_COMPUTE
from dataset ds1
left join dataset ds2
on ds1.tp_n = ds2.tp_n +1
and ds1.dt = ds2.dt
and ds1.mnth = ds2.mnth
and ds1.p_id = ds2.p_id
and ds1.a_br = ds2.a_br
and ds1.d_br = ds2.d_br
and ds1.b_br = ds2.b_br
and ds1.dr = ds2.dr
left join dataset ds3
on ds1.tp_n = ds3.tp_n +2
and ds1.dt = ds3.dt
and ds1.mnth = ds3.mnth
and ds1.p_id = ds3.p_id
and ds1.a_br = ds3.a_br
and ds1.d_br = ds3.d_br
and ds1.b_br = ds3.b_br
and ds1.dr = ds3.dr
left join dataset ds4
on ds1.tp_n = ds4.tp_n +3
and ds1.dt = ds4.dt
and ds1.mnth = ds4.mnth
and ds1.p_id = ds4.p_id
and ds1.a_br = ds4.a_br
and ds1.d_br = ds4.d_br
and ds1.b_br = ds4.b_br
and ds1.dr = ds4.dr
order by 7;

Второй использует разделы внутри подзапроса:

select sub.dt
,sub.mnth
,sub.p_id
,sub.a_br
,sub.d_br
,sub.b_br
,sub.tp_n
,sub.dr
,sub.o_m
,sub.o_n
,case when o_m2 = 0 and o_m3 = 0 and o_m4 = 0 and o_n2 in ('OD03','OT03','MO03') and o_n4 in ('OD03','OT03','MO03') and o_n4 in ('OD03','OT03','MO03') then sub.o_m
else 0 end as TO_COMPUTE
from
(
select ds.dt
,ds.mnth
,ds.p_id
,ds.a_br
,ds.d_br
,ds.b_br
,ds.tp_n
,ds.dr
,ds.o_m
,ds.o_n
,max(ds.o_m) over (partition by ds.dt, ds.mnth, ds.p_id, ds.a_br, ds.d_br, ds.b_br, ds.dr order by ds.tp_n rows between 1 preceding and 1 preceding) as O_M2
,max(ds.o_m) over (partition by ds.dt, ds.mnth, ds.p_id, ds.a_br, ds.d_br, ds.b_br, ds.dr order by ds.tp_n rows between 2 preceding and 2 preceding) as O_M3
,max(ds.o_m) over (partition by ds.dt, ds.mnth, ds.p_id, ds.a_br, ds.d_br, ds.b_br, ds.dr order by ds.tp_n rows between 3 preceding and 3 preceding) as O_M4
,max(ds.o_n) over (partition by ds.dt, ds.mnth, ds.p_id, ds.a_br, ds.d_br, ds.b_br, ds.dr order by ds.tp_n rows between 1 preceding and 1 preceding) as O_N2
,max(ds.o_n) over (partition by ds.dt, ds.mnth, ds.p_id, ds.a_br, ds.d_br, ds.b_br, ds.dr order by ds.tp_n rows between 2 preceding and 2 preceding) as O_N3
,max(ds.o_n) over (partition by ds.dt, ds.mnth, ds.p_id, ds.a_br, ds.d_br, ds.b_br, ds.dr order by ds.tp_n rows between 3 preceding and 3 preceding) as O_N4
from dataset ds
) sub
order by 7;
person M. Wise    schedule 30.10.2018