2013-04-22 3 views
4

Как можно ссылаться на вычисленное значение из предыдущей строки в SQL-запросе? В моем случае каждая строка является событием, которое каким-то образом управляет одним и тем же значением из предыдущей строки.Ссылка на значение предыдущего исчисляемого значения в Oracle

Необработанные данные выглядят следующим образом:

 
Eventno Eventtype Totalcharge 
3  ACQ   32 
2  OUT   NULL 
1  OUT   NULL 

Допустит, каждый типСобытия = OUT должен половина предыдущего totalcharge строки в колонке под названием Remaincharge:

 
Eventno Eventtype Totalcharge Remaincharge 
3  ACQ   32   32 
2  OUT   NULL   16 
1  OUT   NULL   8 

Я уже попробовал LAG аналитическая функция, но это не позволяет мне получить вычисленное значение из предыдущей строки. Пытался что-то вроде этого:

LAG(remaincharge, 1, totalcharge) OVER (PARTITION BY ...) as remaincharge

Но это не сработало, потому что remaingcharge не может быть найден.

Любые идеи, как достичь этого? Требуется функция аналитики, которая может дать мне кумулятивную сумму, но при условии, что функция вместо этого имеет доступ к предыдущему значению.

Спасибо заранее!

Описание проблемы Обновление

Я боюсь, что мой пример проблема была в целом, вот лучшее описание проблемы:

Что остается totalcharge определяется отношением outqty/(предыдущий remainqty).

 
Eventno Eventtype Totalcharge Remainqty Outqty 
4  ACQ   32   100  0 
3  OTHER  NULL   100  0 
2  OUT   NULL   60   40 
1  OUT   NULL   0   60 
 
Eventno Eventtype Totalcharge Remainqty Outqty Remaincharge 
4  ACQ   32   100  0  32 
3  OTHER  NULL   100  0  32 - (0/100 * 32) = 32 
2  OUT   NULL   60   40  32 - (40/100 * 32) = 12.8 
1  OUT   NULL   0   60  12.8 - (60/60 * 12.8) = 0 

ответ

2

вариация на Бена ответьте на использование оговорки, которая, как представляется, позаботится о ваших обновленных требованиях:

select eventno, eventtype, totalcharge, remainingqty, outqty, 
    initial_charge - case when running_outqty = 0 then 0 
    else (running_outqty/100) * initial_charge end as remainingcharge 
from (
    select eventno, eventtype, totalcharge, remainingqty, outqty, 
     first_value(totalcharge) over (partition by null 
      order by eventno desc) as initial_charge, 
     sum(outqty) over (partition by null 
      order by eventno desc 
      rows between unbounded preceding and current row) 
      as running_outqty 
    from t42 
); 

Кроме него дает 19.2 вместо 12.8 для третьего ряда, но это то, что ваша формула предполагает, что это должно быть:

EVENTNO EVENT TOTALCHARGE REMAININGQTY  OUTQTY REMAININGCHARGE 
---------- ----- ----------- ------------ ---------- --------------- 
     4 ACQ   32   100   0    32 
     3 OTHER      100   0    32 
     2 OUT       60   40   19.2 
     1 OUT       0   60    0 

Если добавить еще один раскол, так что идет от 60 до нуля в два этапа, с другой не-OUT запись в смеси тоже:

EVENTNO EVENT TOTALCHARGE REMAININGQTY  OUTQTY REMAININGCHARGE 
---------- ----- ----------- ------------ ---------- --------------- 
     6 ACQ   32   100   0    32 
     5 OTHER      100   0    32 
     4 OUT       60   40   19.2 
     3 OUT       30   30    9.6 
     2 OTHER      30   0    9.6 
     1 OUT       0   30    0 

Там есть предположение, что оставшееся количество соответствует, и вы можете эффективно отслеживать нарастающий итог того, что было раньше, но из данных вы показали, что выглядит правдоподобно , Внутренний запрос вычисляет, что выполняется общее количество для каждой строки, а внешний запрос выполняет расчет; это может быть сжато, но, надеюсь, более ясное, как это ...

+0

Я одобрил ранее, но это решает. Текущая строка - это различие ... Я не считал это. – Ben

+0

Большое спасибо @Ben и @ alex-poole! Думаю, мы поняли. Сделал некоторые незначительные изменения в случае увеличения оставшейся части (может случиться). Вместо того, чтобы делить на фиксированный 100, необходимо использовать предыдущий остаток. Получил его с помощью функции LAG(): LAG (fae.remainqty, 1, 0) OVER (PARTITION BY fac.facid ORDER BY eventno DESC) AS previous_remainqty – Kristoffer

4

В вашем случае вы могли бы работать значение первым с помощью FIRST_VALUE() аналитическую функцию и силу 2, что вы должны разделить на с RANK() в суб-запроса, а затем использовать это. Это очень специфичные для вашего примера, но должно дать вам общее представление:

select eventno, eventtype, totalcharge 
    , case when eventtype <> 'OUT' then firstcharge 
      else firstcharge/power(2, "rank" - 1) 
     end as remaincharge 
    from (select a.* 
       , first_value(totalcharge) over 
        (partition by 1 order by eventno desc) as firstcharge 
       , rank() over (partition by 1 order by eventno desc) as "rank" 
      from the_table a 
       ) 

Вот SQL Fiddle продемонстрировать. Я ничего не разбил на разделы, потому что у вас ничего нет в ваших исходных данных для разделения на ...

+1

+1, но я думаю, вам нужно добавить «case» в eventype, а также использовать «rank-1», чтобы получить запрос OP resulat http: // www .sqlfiddle.com/#! 4/c7eda/13 –

+0

Большое спасибо @ABCade; Я полностью пропустил это требование. – Ben

+0

Я боюсь, что мой вопрос был испорчен, постаравшись задать общую проблему. Теперь он обновлен с описанием проблемы, намного более приближенным к реальности. Извините за путаницу, я очень ценю вашу помощь. – Kristoffer

1

Ben's answer тем лучше один (вероятно, работать лучше), но вы также можете сделать это следующим образом:

select t.*, (connect_by_root Totalcharge)/power (2,level-1) Remaincharge 
from the_table t 
start with EVENTTYPE = 'ACQ' 
connect by prior eventno = eventno + 1; 

Я думаю, что легче читать

Here is a demo

 Смежные вопросы

  • Нет связанных вопросов^_^