Paweł Koźbiał

Paweł Koźbiał Student,
Politechnika
Częstochowska

Temat: [PostgreSQL] - sumowanie wartości w pętli FOR

witam, mam problem z taką funkcją:
create or replace function testing(text) returns void as
$BODY$
declare
i record;
trader alias for $1;
suma_net_pl numeric(8,2);
begin
for i in select * from baza where trader_id like trader
LOOP
suma_net_pl := suma_net_pl + sum(i.net_pl); <---------
end LOOP;
RAISE NOTICE 'suma is %', suma_net_pl;
end;
$BODY$
language 'plpgsql';

jak sprawić aby zsumowało wszystkie wartości w kolumnie net_pl??
Daniel Podlejski

Daniel Podlejski DBA,
SysAdmin/DevOps,
backend developer

Temat: [PostgreSQL] - sumowanie wartości w pętli FOR

Ale czemu funkcją? Co chcesz osiągnąć?
Albo wymyśliłeś wydumany, ale słaby przykład, który ma oddać coś innego, co robisz, ale nie chcesz tego z jakiegoś powodu pokazać, albo po prostu błądzisz po omacku.

Jeśli chcesz zsumować wartosci z kolumny net_pl dla wszystkich wierszy, w których trader_id pasuje do wzorca, to użyj po prostu:
"select sum(net_pl) from baza where trader_id like ?"

BTW - nie wiem jakiej konwencj używasz, ale trader_id sugeruje, że to integer, i klucz obcy tabeli trader(s) - jeśli tak, to like jest bez sensu. Jeśli to rzeczywiście integer - użyj "where trader_id = ?"
Paweł Koźbiał

Paweł Koźbiał Student,
Politechnika
Częstochowska

Temat: [PostgreSQL] - sumowanie wartości w pętli FOR

już mam rozwiązanie:

CREATE OR REPLACE FUNCTION testing(text) returns void AS
$BODY$
DECLARE
i RECORD;
trader alias FOR $1;
suma_net_pl numeric(8,2);
BEGIN
suma_net_pl := 0; <-----
FOR i IN SELECT * FROM baza WHERE trader_id LIKE trader
LOOP
suma_net_pl := suma_net_pl + i.net_pl; <-----
END LOOP;
RAISE NOTICE 'suma is %', suma_net_pl;
END;
$BODY$
language 'plpgsql';
Grzegorz D.

Grzegorz D. PL/SQL Developer

Temat: [PostgreSQL] - sumowanie wartości w pętli FOR

ojejej...

Czemu nie tak jak proponował Daniel?
Paweł Koźbiał

Paweł Koźbiał Student,
Politechnika
Częstochowska

Temat: [PostgreSQL] - sumowanie wartości w pętli FOR

Chciałem tylko sprawdzić czy to będzie działać, bo męczę się z pewną funkcją i nie mogę nic wykombinować.
Opiszę o co mi chodzi, to mam nadzieję, że ktoś pomoże:

mam główną tabelę 'baza', która ma kolumny:
trader_id, order_nbr integer, symbol, net_pl, event_date, time
dane do niej wczytuję z pliku *.csv.
Szukana funkcja zwracałaby wartości takie jak zapytanie:
select trader_id, sum(net_pl), count(distinct order_nbr), event_date from baza
które następnie byłyby zapisywane w innej tabeli, to by się odbywało automatycznie za pomocą trigger ... for each row.

Nie wiem jak się za to zabrać, jakieś pomysły?Paweł Koźbiał edytował(a) ten post dnia 11.05.11 o godzinie 00:19

konto usunięte

Temat: [PostgreSQL] - sumowanie wartości w pętli FOR

Inserta można zrobić z selecta:
http://www.postgresql.org/docs/8.4/static/sql-insert.html
Każdą kolumnę można określić subselectem...

konto usunięte

Temat: [PostgreSQL] - sumowanie wartości w pętli FOR

primo uczymy się pracować na zbiorach, bo to co prezentujesz to typowe podejście porogramisty

secundo uczymy się podstaw SQL-a, bo to trochę żenada nie umieć zrobić agregacji albo select into - takich rzeczy to ja na podstawach Access-a uczę
Paweł Koźbiał

Paweł Koźbiał Student,
Politechnika
Częstochowska

Temat: [PostgreSQL] - sumowanie wartości w pętli FOR

na chwilę obecną doszedłem do takiego rozwiązania:

create or replace function wypelnij_tabele() returns trigger as
$BODY$
begin
IF (TG_OP = 'INSERT') THEN

insert into wyniki_dzienne(trader_id, suma, ile_tradow, event_date)
(select trader_id, sum(net_pl), count(distinct order_nbr), event_date from baza
group by trader_id, event_date);

END IF;
RETURN NULL;
end;
$BODY$
language 'plpgsql';

CREATE TRIGGER wypelnij_tabele
AFTER INSERT ON baza
FOR EACH ROW
EXECUTE PROCEDURE wypelnij_tabele();

problem polega na tym, że dla każdego inserta do tabeli baza jest wykonywana funkcja wypelnij_tabele() i otrzymuję powielanie danych: 900 (insert do baza) * 5 (wyniki z funkcji wypelnij_tabele()) = 4500 wierszy w tabeli wyniki_dzienne (powinno być tylko 5 wierszy)

jak zmienić aby 'insert into wyniki_dzienne...' wykonał się tylko jeden raz?
Daniel Podlejski

Daniel Podlejski DBA,
SysAdmin/DevOps,
backend developer

Temat: [PostgreSQL] - sumowanie wartości w pętli FOR

Updateować tabelę wyniki_dzienne jeśli rekordy z sumą istnieją, a wstawiać jeśli nie.
BTW funkcja którą napisałeś jest bardzo nieoptymalna. Po co sumujesz za każdym razem, jeśli masz trigger? Wystarczy dodawać nowe wartości. Coś w rodzaju (pisane z palca, nie sprawdzane):

CREATE OR REPLACE FUNCTION update_wyniki_dzienne() RETURNS trigger AS $$
DECLARE
s INTEGER;
BEGIN
SELECT suma INTO sum FROM wyniki_dzienne WHERE trader_id = NEW.trader_id AND event_date = NEW.event_date;

IF s IS NULL THEN
INSERT INTO wyniki_dzienne (trader_id, event_date, suma) VALUES (NEW.trader_id, NEW.event_date, NEW.net_pl);
ELSE
UPDATE wyniki_dzienne SET suma = suma + NEW.net_pl WHERE trader_id = NEW.trader_id AND event_date = NEW.event_date;
END IF;

RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Z order_nbr musisz sobie sam poradzić - nie chcę zgadywać jaka jest tego logika. Być może wystarczy dodawać 1 do pola z licznikiem.

konto usunięte

Temat: [PostgreSQL] - sumowanie wartości w pętli FOR

Można zrobić triggery na Insert / Update / Delete - zamiast za każdym razem liczyć - można podbijać / zmniejszać licznik. Trzeba select for update na tabelach z wynikami robić, żeby się licznik nie rozjechał. Przy update też trzeba zagwarantować, żeby zmiany odbywały się w ściśle określonej kolejności.

Następna dyskusja:

Sumowanie w polu tekstowym ...




Wyślij zaproszenie do