[sql] jak policzyc ilosc z dwoch kolumn ?

0

Witam, pracuje nad dwiem atbelkami i probuje zrobic takie cos:

id | ilosc_add | ilosc_remove |
--+----------+-------------+
1 | 1000 | 0 |
2 | 0 | 200 |
3 | 0 | 300 |
4 | 1000 | 0 |

kiedy chce wykonac zapytanie chcialbym zeby wynik byl taki:

ilosc_add | ilosc_remove | ilosc_total
---------+--------------+--------------
1000 | 0 | 1500
0 | 300 | 500
0 | 200 | 800
1000 | 0 | 1000

chodzi o to zeby w wyniku wyswietlao mi sie:

  • w odwrotnej kolejnosci niz jest w tabelce
  • zeby z liczylo ile zostalo ilosci

teraz jak to powino wygladc jak pobrac poprzednia ilosc
ja to widze tak:

ILOSC_TOTAL + od pola ILOSC_ADD odejmuje ILOSC_REMOVE i to jest moj wynik ILOSC_TOTAL
czyli 0 + 1000 - 0 = 1000

teraz krok nastepny
ILOSC_TOTAL ( z poprzedniego rekordu) + ILOSC_ADD odejmuje ILOSC_REMOVE i mam ILOSC_TOTAL
czyli: 1000 (z poprzedniego) + 0 - 200 = 800

krok nastepny
ILOSC_TOTAL ( z rekordu wyzej) + ILOSC_ADD - ILOSC_REMOVE = ILOSC_TOTAL
800 + 0 - 300 = 500

i ostatnie
ILOSC_TOTAL (z rek wyzej) + ILOSC_ADD - ILOSC_REMOVE = ILOSC_TOTAL
500 + 1000 - 0 = 1500

Czy da sie to wykonac jakos w jednym zapytaniu jak to zrobic ?

0

tak to tylko w erze albo stored proc

0

W zasadzie chodzi o to zeby po wykonaniu obliczenia
ILOSC_TOTAL - ILOSC_ADD - ILOSC REMOVE = ILOSC_TOTAL zeby to zapamietac i uzyc jako zmiennej.
Da sie to powolac jaos wjednym zapytaniu czy musze tworzyc jakies funkcje czy jak to ruszyc ?
moze macie jakis pomysl jakies wskazowki ?

0

tego nie ma chyba w "ogólnym sql", jedynie może jest jakieś rozwiązanie dla twojej bazy ale nie podałeś jak się ona wabi

0

Pracuje z baza PostgreSQL - tu w zasadzie chodzi o jakas zmienna ktora by zapamietala wynik z ostatniej operaci odejmowania. tak jakby bylo:

SELECT
(TEMP + ADD - REMOVE = total) ;
TEMP = TOTAL;
END

Kurcze nie znam sie na funkcjach ani jak by to moglo wygladac.
poradzacie cos prosze

0

najpierw

CREATE TYPE "public"."t_out" AS (
  "id" INTEGER,
  "add" INTEGER,
  "remove" INTEGER,
  "total" INTEGER
);

a potem

CREATE OR REPLACE FUNCTION "public"."test1" () RETURNS SETOF "public"."t_out" AS
$body$
DECLARE
  rec RECORD;
  out t_out;
BEGIN
  out.total = 0;
  FOR rec IN SELECT id, ilosc_add, ilosc_remove FROM table1 ORDER BY id ASC LOOP
    out.id = rec.id;
    out.add = rec.ilosc_add;
    out.remove = rec.ilosc_remove;
    out.total = out.total + out.add - out.remove;
    RETURN NEXT out;
  END LOOP;
END;
$body$
LANGUAGE 'plpgsql' IMMUTABLE RETURNS NULL ON NULL INPUT SECURITY INVOKER;

i zapytanie

SELECT * FROM test1() ORDER BY id DESC

po helpa zapraszam na http://www.postgresql.org/docs/8.1/interactive/index.html

0

Zabieram sie za etstowanie i przede wszystkim za zrozumienie tej funkcji bo robielm rozne ale nie udawaly sie dziekuej za pomoc. musze to wybadac dokladanie bo to zapewne funkcja ktora bedzie mi sie powtarzala w miare rozrastajacego sie kodu. dzieki

0

Jeżeli dobrze Cię zrozumiałem to to zapytanie daje wynik o który Ci chodzi . Sprawdzałem.

SELECT *, @temp := @temp + (ilosc_add-ilosc_remove) FROM tabela1 ORDER BY id DESC;

A ściślej

SELECT *, @temp := @temp + (ilosc_add-ilosc_remove) AS ilosc_total FROM tabela1 ORDER BY id DESC;

0

hej, fajne, nie wiedziałem o tym, ale to działa w postgre ?
za to kolejność nie ta, i kolejne wywołanie w tym samym połaczeniu powoduje zafałszowanie wartości bo @temp nie jest zerowane więc może:

SELECT ilosc_add, ilosc_remove, ilosc_total FROM (SELECT id, ilosc_add, ilosc_remove, @temp := @temp + (ilosc_add - ilosc_remove) AS ilosc_total FROM nazwa_tabeli, (SELECT @temp := 0) A ORDER BY id ASC) B ORDER BY id DESC;

a może lepiej nie analizuj funkcji (bo ci "się będzie powtarzać przy rozrastającym kodzie") tylko analizuj sens swoich tabeli (żeby ci nie były potrzebne takie funkcje a baza danych nie robiła tego do czego nie służy)

0

Jestescie fantastyczni. wlasnie musze terz sprawdzic to wszystko :} no nie.
jak sprawdze dopisze co i jak. czyli zamiast funkcji lepiej w zapytaniu?

ok sprawdzilem kiedy w powyzszym zapytaniu wpisze
@temp := 0

wyswietla mi blad:
syntax error at or near ":" at character 199

kiedy usuwam znak : wyswietla mi taki komunikat:
column "temp" does not exist

czy mam dodac kolumne do tabeli ?
dodam i zobace co sie stanie

Dodalem pole TEMP do tabeli i teraz mam taka wiadomosc:
subquery in FORM may not refer to other relations of same query level

p.s. a do czego sluza triggery i czy warto je stosowac?
wiem ze google ale chcialbym poznac zdanie ekspertow

0

no ja nie powiedziałem że lepiej w zapytaniu niż w funkcji, tym bardziej że tutaj jak widać to zapytanie w tej bazie nie działa jednak więc pozostacje tylko odpowiedź Miśkad

0

ale jak wpisuje funkcje ta miska to mam taki komunikat:

syntax error at near RECORD at character 17
czemu tak?

0

wersja Miśkad działa poprawnie na PostgreSQL powyżej 7 czyli na PostgreSQL 8 :)

na siódemce trzeba $ zamienić na średniki i powinno chodzić. Ale nie testowałem. Nie mam dostępu do takiego serwera.

Co do triggerów. Są to procedury składowane ale.... Trigger - wyzwalacz. Sama nazwa wskazuje że są to procedury składowane wyzwalane. Są one stosowane bardzo często i są również bardzo użyteczne. Wyzwolić możesz procedurę na przykład po jakims zdarzeniu (BEFORE) lub przed (AFTER).

Prosty przykład. Chcesz na przykład przed usunięciem wiersza zapisać go do archiwum. Standardowo być pisał zapytanie wczytujące następnie zapisujące i na końcu usuwające. Do tego możesz użyć triggera, w którym napiszesz że wiersz który ma być usunięty ma równocześnie zostać przeniesiony do archiwum. Wystarczy użyć BEFORE DELETE i już wiesz co dalej ;). Przy kodzeniu na przykład w php unikasz rozpisywania tego na PHP ;)

Można definiować różne akcje. na przykład przed update'm sprawdzić czy przypadkiem jakaś wartość nie osiągnęła maksymalnego pułapu. triggery są bardzo użyteczne tak samo jak procedury składowane. Załóżmy że dodanie użytkownika do bazy danych wiąże się z wykonaniem szeregu czynności. Czeu nie napisać procedury składowanej? :> Unikamy dzięki temu kodzenia w php i możemy dodawać użytkownika w dowolnym miejscu. Mało tego! Pisząc następny system jakiś nie musimy myśleć o kodzie php który zostanie wykorzystany do tego. wystarczy skopiować procedurę z jednej bazy do drugiej, pozmieniać ewentualnie nazwy tabel i mamy gotowe. ;)

0
ziutek napisał(a)

Jeżeli dobrze Cię zrozumiałem to to zapytanie daje wynik o który Ci chodzi . Sprawdzałem.

SELECT *, @temp := @temp + (ilosc_add-ilosc_remove) FROM tabela1 ORDER BY id DESC;

A ściślej

SELECT *, @temp := @temp + (ilosc_add-ilosc_remove) AS ilosc_total FROM tabela1 ORDER BY id DESC;

a co za cudo takiego SQLa przepuści, bo na 100% nie postgres

Adamo: a nie lepiej prostą procedurę zamiast podzapytań?

0

uzywam postgresa 7.4 sprawdze jutro te sredniki. czyli trigery to faktycznie swietna rzecz. wlasciwie lepiej napisac wszystkie proceurki w sql niz w php sie meczyc faktycznie hmmm. na razie mocno cwicze ta funkcje zeby j ajakos dodac

1 użytkowników online, w tym zalogowanych: 0, gości: 1