SQL | Обновить запрос с левым соединением и условием обращения - PullRequest
0 голосов
/ 03 мая 2020
TABLE A


ID , PER , DATE , CALC
1 , 11 , 1-Apr , 1
1 ,6, 2-Apr , 4
2 ,7 , 1-apr ,2
2 , 12 , 2-apr , 3
3 , 13 , 2-apr , 1
4 , 8 , 2-ape , 2

Требуется написать запрос на обновление на основе нижеуказанного условия

Условием для столбца cal c является Cal c = 1, когда per больше 10% и нет предыдущей записи

Cal c = 2, когда per больше 5% и меньше 10%, и нет предыдущей записи

Cal c = 3, когда per увеличено с последней записи

Cal c = 4, когда значение per уменьшается с последней записи

1 Ответ

2 голосов
/ 03 мая 2020

Вы можете использовать функцию Oracles LAG для доступа к предыдущему ряду ( ссылка ). Остальное - большой оператор CASE, обрабатывающий различные состояния.

В моем примере ниже я предполагаю, что столбцы ID и DATE являются первичными ключами в демонстрационной таблице. Вы должны проверить части, где NULL используется для CAL C (отмечено 2 знаками вопроса). Это состояния не определены вашим описанием.

BEGIN
    EXECUTE IMMEDIATE 'drop table table_a';
EXCEPTION
    WHEN OTHERS THEN NULL;
END;
/
create table table_a (
    "ID" number,
    "PER" number,
    "DATE" date,
    "CALC" number
);
/
insert into table_a 
select 1 "ID", 11 "PER", trunc(sysdate)-1 "DATE", null "CALC" from dual
union all
select 1 "ID", 6 "PER", trunc(sysdate) "DATE", null "CALC" from dual
union all
select 2 "ID", 7 "PER", trunc(sysdate)-1 "DATE", null "CALC" from dual
union all
select 2 "ID", 12 "PER", trunc(sysdate) "DATE", null "CALC" from dual
union all
select 3 "ID", 13 "PER", trunc(sysdate) "DATE", null "CALC" from dual
union all
select 4 "ID", 8 "PER", trunc(sysdate) "DATE", null "CALC" from dual
/

update table_a
set ("CALC") = (
    with tmp_prev as (
    select 
        "ID",
        "PER",
        "DATE",
        LAG("PER") OVER (PARTITION BY "ID" ORDER BY "ID","DATE") "PREV_PER"
    from table_a
    )
    select 
        case when "PREV_PER" is null 
            then
                case when "PER" > 10 then 1 
                else
                    case when "PER" > 5 and "PER" < 10 
                        then 2
                        else null -- ?? =10 or <=5
                    end
                end
            else
                case when "PER" > "PREV_PER" 
                    then 3
                    else 
                        case when "PER" < "PREV_PER"
                            then 4
                            else null -- ?? equal
                        end
                end
            end calc_new
    from tmp_prev
    where table_a."ID"=tmp_prev."ID" and table_a."DATE"=tmp_prev."DATE"
);
/

select * from table_a;
/

Результат:

        ID        PER DATE           CALC
---------- ---------- -------- ----------
         1         11 02.05.20          1
         1          6 03.05.20          4
         2          7 02.05.20          2
         2         12 03.05.20          3
         3         13 03.05.20          1
         4          8 03.05.20          2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...