[Oracle] Implementacja logiki z excel

[Oracle] Implementacja logiki z excel
C6
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 197
0

Mam pewien problem, piszę logikę zawartą w excelu w Oracle SQL.
Tabelka wynikowa ma poniższe dane:

UMOWA || PRZEKR
100 || 0
100 || 150
100 || 450

I teraz chcę nową kolumn WYNIK która powinna mieć logikę:

DLA TRZECIEGO REKORDU:

Kopiuj
JEŻELI ( PRZEKR <= UMOWA;0;PRZEKR - UMOWA ) - SUMA (WYNIK$1:WYNIK$2)

Czyli powinien być wynik:

UMOWA || PRZEKR || WYNIK
100 || 0 || 0
100 || 150 || 50 ---> (150-100) - 0
100 || 450 || 300 --- > (450-100) - 50

Mam prosty CASE w sql:

Kopiuj
CASE WHEN p3.PRZEKR < UMOWA THEN 0 ELSE p3.PRZEKR - UMOWA END 

Nie wiem jak w zapytaniu dodać tą dynamiczną SUMĘ, ma ktoś jakąś propozycję?

YA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2384
0

W excelu masz identyfikator wiersza i w formule możesz odnosić się do poprzednich wierszy, a w SQLu jak będziesz miał tabelkę, co to znaczy "poprzednie" ?

C6
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 197
0
yarel napisał(a):

W excelu masz identyfikator wiersza i w formule możesz odnosić się do poprzednich wierszy, a w SQLu jak będziesz miał tabelkę, co to znaczy "poprzednie" ?

No tak nie dopisałem co jest jeszcze w tabelce. Wygląda to tak:

DATA || UMOWA || PRZEKR || WYNIK
18/11/16 || 100 || 0 || 0
18/11/19 || 100 || 150 || 50 ---> (150-100) - 0
19/11/22 || 100 || 450 || 300 --- > (450-100) - 50

Czyli PRZEKR można powiedzieć jest wyliczana narastająco po dniach od początku roku (czyli partition by YEAR).
Dla danego produktu są dane tylko dla niektórych DNI - nie ma wszystkich dni w tabeli, tylko tam gdzie są dane.

Moja kolumna WYNIKI ma być wyliczana również narastająca i powinna odejmować SUME z poprzednich dni od początku roku.

Marcin.Miga
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2794
1

SUM() OVER()

YA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2384
0

Skoro masz datę, to można sumować po zdefiniowanym okienku.

  1. Wyliczasz WYNIK
Kopiuj
select t.*, case ... end wynik from tabelka; 
  1. Wyliczasz z tak przygotowanego zbioru sumy narastajace:
Kopiuj
select 
    u.*,
    wynik - sum(wynik) over (partition by year order by year RANGE BETWEEN UNBOUNDED AND CURRENT ROW)  suma_narastajaca
from 
  (select t.*, case ... end wynik from tabelka) u;

Nie testowałem, ale jak zrobisz przykładowe dane na sqlfiddle, to będzie na czym sprawdzać ;)

C6
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 197
0
Marcin.Miga napisał(a):

SUM() OVER()

Możesz rozwinąć myśl?

Kopiuj
, p4.wynik - (SUM(p4.wynik ) OVER (partition by p4.PRODUT, p4.YEAR order by p4.DZIEN RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW))  B1

Mam taką na razie formułe, jednak ta suma bierze mi pod uwagę również CURRENT ROW w range between. Czy się użyć żeby ten range ustawić od pierwszego rekordu do coś w s tylu PREVIOUS ROW - w sensie z poprzedniego dostępnego dnia (jeżeli nie ma poprzedniego to 0?

YA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2384
1

Masz funkcję LAG, która "zagląda do poprzednich wierszy" i może skorygować sumę.

C6
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 197
1
yarel napisał(a):

Masz funkcję LAG, która "zagląda do poprzednich wierszy" i może skorygować sumę.

Oo widzisz! Nie znałem takiej funkcji, ale już rzuciłem okiem na dokumentację i faktycznie o coś takiego chodziło.
Wyliczenia poprzedniej wartości zrobiłem mniej więcej tak:

Kopiuj
NVL(LAG(w1.WYNIK,1) OVER (partition by w1.PRODUKT, w1.YEAR ORDER BY w1.DZIEN),0) as PREV_VALUE

I później w kolejnym kroku odjąłem tylko WYNIK - PREV_VALUE i wygląda że jest w porządku.

DzięKI!

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.