Chcę znaleźć skumulowaną lub bieżącą ilość pola i wstawić ją z przemieszczania do tabeli. Moja struktura inscenizacji wygląda mniej więcej tak:
ea_month id amount ea_year circle_id
April 92570 1000 2014 1
April 92571 3000 2014 2
April 92572 2000 2014 3
March 92573 3000 2014 1
March 92574 2500 2014 2
March 92575 3750 2014 3
February 92576 2000 2014 1
February 92577 2500 2014 2
February 92578 1450 2014 3
Chcę, aby moja tabela docelowa wyglądała mniej więcej tak:
ea_month id amount ea_year circle_id cum_amt
February 92576 1000 2014 1 1000
March 92573 3000 2014 1 4000
April 92570 2000 2014 1 6000
February 92577 3000 2014 2 3000
March 92574 2500 2014 2 5500
April 92571 3750 2014 2 9250
February 92578 2000 2014 3 2000
March 92575 2500 2014 3 4500
April 92572 1450 2014 3 5950
Jestem naprawdę zdezorientowany, jak osiągnąć ten wynik. Chcę osiągnąć ten wynik za pomocą PostgreSQL.
Czy ktoś może zasugerować, jak zabrać się do osiągnięcia tego zestawu wyników?
sql
postgresql
window-functions
analytic-functions
cumulative-sum
Yousuf Sultan
źródło
źródło
Odpowiedzi:
Zasadniczo potrzebujesz funkcji okna . To standardowa funkcja w dzisiejszych czasach. Oprócz oryginalnych funkcji okna, możesz użyć dowolnej funkcji agregującej jako funkcji okna w Postgresie, dołączając
OVER
klauzulę.Szczególna trudność polega na tym, aby uzyskać partycje i porządek sortowania:
SELECT ea_month, id, amount, ea_year, circle_id , sum(amount) OVER (PARTITION BY circle_id ORDER BY ea_year, ea_month) AS cum_amt FROM tbl ORDER BY circle_id, month;
I nie
GROUP BY
.Suma dla każdego wiersza jest obliczana od pierwszego wiersza w partycji do bieżącego wiersza - lub dokładniej cytując instrukcję :
... która jest sumą skumulowaną lub sumaryczną, o którą myślisz. Odważne podkreślenie moje.
Wiersze z samo
(circle_id, ea_year, ea_month)
to „rówieśnicy” w tym zapytaniu. Wszystkie z nich pokazują tę samą sumę kumulacyjną z dodanymi do niej wszystkimi odpowiednikami. Ale zakładam, że twoja tabela jestUNIQUE
włączona(circle_id, ea_year, ea_month)
, wtedy porządek sortowania jest deterministyczny i żaden wiersz nie ma rówieśników.Teraz
ORDER BY ... ea_month
nie będzie działać z ciągami nazw miesięcy . Postgres będzie sortował alfabetycznie zgodnie z ustawieniami lokalnymi.Jeśli masz rzeczywiste
date
wartości zapisane w tabeli, możesz je poprawnie posortować. Jeśli nie, proponuję zastąpićea_year
iea_month
jedną kolumnąmon
typudate
w Twojej tabeli.Zmień to, co masz
to_date()
:Do wyświetlania możesz uzyskać oryginalne ciągi z
to_char()
:Jeśli utkniesz w niefortunnym projekcie, zadziała:
SELECT ea_month, id, amount, ea_year, circle_id , sum(amount) OVER (PARTITION BY circle_id ORDER BY mon) AS cum_amt FROM (SELECT *, to_date(ea_year || ea_month, 'YYYYMonth') AS mon FROM tbl) ORDER BY circle_id, mon;
źródło
range unbounded preceding
, które jest domyślnie ustawione na , czyli to samo corange between unbounded preceding and current row
. Dlatego,sum()
gdy jest używana jako funkcja okna, tworzy bieżącą sumę - podczas gdy inne funkcje okna nie mają tej domyślnej ramki.PARTITION
nie zawsze jest potrzebne do utworzenia sumy bieżącej): stackoverflow.com/a/5700744/175830