Igor Piotr I.

Igor Piotr I. IT manager/Senior
Oracle Developer

Temat: SQL mnożenie kolejnych rekordów

mam w oraclu potrzebe zrobienie selecta z tablicy który będzie mnozył przez siebie kolejne wartości licznowe.

przykład
ilosc
3
7
2

select mnożenie(ilosc) from tablica -> (3*7*2)=42

może ktoś wpadnie na jakiś fajny pomysł.
Grzegorz G.

Grzegorz G. ASE / Systems
Architect, Syniverse

Temat: SQL mnożenie kolejnych rekordów

User defined aggregate. (>= 9i).

konto usunięte

Temat: SQL mnożenie kolejnych rekordów

Pomysł jest bardzo prosty - procedura składowana/funkcja z kursorem w środku...
Izabela Korzińska

Izabela Korzińska Architekt /
Developer ETL/TEam
Leader, Roche Polska

Temat: SQL mnożenie kolejnych rekordów

Ale to chyba nie miał być PL/SQL, tylko zwykły select. Proponuję:

SELECT POWER( 2, SUM( LOG( 2, kolumna_która_mnozymy )))
FROM tabela

Tak przemnożysz wszystkie wartości w kolumnie. Nie znalazłam niestety funkcji, która by to pomnożyła :)

pozdr
IzaIzabela Korzińska edytował(a) ten post dnia 08.01.09 o godzinie 09:27

konto usunięte

Temat: SQL mnożenie kolejnych rekordów

Izabela Korzińska:
SELECT POWER( 2, SUM( LOG( 2, kolumna_która_mnozymy )))
FROM tabela

Będą błędy zaokrągleń. Tzn 2 * 3 * 7 to nie będzie całkowite 42.

konto usunięte

Temat: SQL mnożenie kolejnych rekordów

Igor Piotr I.:
select mnożenie(ilosc) from tablica -> (3*7*2)=42

może ktoś wpadnie na jakiś fajny pomysł.

Jeśli to musi być select to może pipelined function ? :)

create or replace type tnn as table of number;
/

FUNCTION MNOZENIE RETURN tnn PIPELINED
AS
x NUMBER;
BEGIN
x := 1;
FOR i IN (SELECT NVL (liczba, 1) y FROM tablica)
LOOP
x := x * i.y;
END LOOP;
PIPE ROW (x);
RETURN;
END;

select * from table(mnozenie)

:-)

Aaa ... trzeba jeszcze obsłużyć sytuację braku wierszy, pewnie wówczas powinien być NULL albo zero, a w/w przykład zwróci 1.Krzysztof P. edytował(a) ten post dnia 08.01.09 o godzinie 09:49
Izabela Korzińska

Izabela Korzińska Architekt /
Developer ETL/TEam
Leader, Roche Polska

Temat: SQL mnożenie kolejnych rekordów

Krzysztof P.:
Izabela Korzińska:
SELECT POWER( 2, SUM( LOG( 2, kolumna_która_mnozymy )))
FROM tabela

Będą błędy zaokrągleń. Tzn 2 * 3 * 7 to nie będzie całkowite 42.

Nie będzie żadnych błędów. To są 2 połączone wzory - prawa dla algorytmów.
Izabela Korzińska

Izabela Korzińska Architekt /
Developer ETL/TEam
Leader, Roche Polska

Temat: SQL mnożenie kolejnych rekordów

Krzysztof P.:
Igor Piotr I.:
select mnożenie(ilosc) from tablica -> (3*7*2)=42

może ktoś wpadnie na jakiś fajny pomysł.

Jeśli to musi być select to może pipelined function ? :)

create or replace type tnn as table of number;
/

FUNCTION MNOZENIE RETURN tnn PIPELINED
AS
x NUMBER;
BEGIN
x := 1;
FOR i IN (SELECT NVL (liczba, 1) y FROM tablica)
LOOP
x := x * i.y;
END LOOP;
PIPE ROW (x);
RETURN;
END;

select * from table(mnozenie)

:-)

Aaa ... trzeba jeszcze obsłużyć sytuację braku wierszy, pewnie wówczas powinien być NULL albo zero, a w/w przykład zwróci 1.Krzysztof P. edytował(a) ten post dnia 08.01.09 o godzinie 09:49

jest decode, jest nvl...

konto usunięte

Temat: SQL mnożenie kolejnych rekordów

Izabela Korzińska:
Nie będzie żadnych błędów. To są 2 połączone wzory - prawa dla algorytmów.

Processing ...
select liczba from tablica

Query finished, retrieving results...
LICZBA
--------------------------------------
3
7
2

3 row(s) retrieved

Processing ...
SELECT POWER( 2, SUM( LOG( 2, liczba ))) FROM tablica

Query finished, retrieving results...
POWER(2,SUM(LOG(2,LICZBA)))
-----------------------------------------
42,00000000000000000000000000000000000073

1 row(s) retrieved

W "real life" może i nie byłoby, ale procesor musi zaokrąglać i nie ma na to rady.

konto usunięte

Temat: SQL mnożenie kolejnych rekordów

Izabela Korzińska:
jest decode, jest nvl...

Jest, ale mi chodziło o wybór wyniku, a nie sposobu.
Izabela Korzińska

Izabela Korzińska Architekt /
Developer ETL/TEam
Leader, Roche Polska

Temat: SQL mnożenie kolejnych rekordów

Krzysztof P.:
[...]
Query finished, retrieving results...
POWER(2,SUM(LOG(2,LICZBA)))
-----------------------------------------
42,00000000000000000000000000000000000073
W "real life" może i nie byłoby, ale procesor musi zaokrąglać i nie ma na to rady.

mhm.. fakt, przy bardzo dużej ilości liczb po zaokrągleniu wyjdzie inny wynik, niż powinien.

konto usunięte

Temat: SQL mnożenie kolejnych rekordów

Izabela Korzińska:
Krzysztof P.:
[...]
Query finished, retrieving results...
POWER(2,SUM(LOG(2,LICZBA)))
-----------------------------------------
42,00000000000000000000000000000000000073
W "real life" może i nie byłoby, ale procesor musi zaokrąglać i nie ma na to rady.

mhm.. fakt, przy bardzo dużej ilości liczb po zaokrągleniu wyjdzie inny wynik, niż powinien.

Niezupełnie. Nawet w tym prostym przypadku jeśli zrobi się porównanie:

[wynik] - 42 = 0

to już będzie fałszywe... Kwestia tego jaki źródłowy typ danych ma być brany pod uwagę (int czy numeric czy float...)Piotr Likus edytował(a) ten post dnia 08.01.09 o godzinie 11:28
Izabela Korzińska

Izabela Korzińska Architekt /
Developer ETL/TEam
Leader, Roche Polska

Temat: SQL mnożenie kolejnych rekordów

Piotr Likus:
Izabela Korzińska:
Krzysztof P.:
[...]
Query finished, retrieving results...
POWER(2,SUM(LOG(2,LICZBA)))
-----------------------------------------
42,00000000000000000000000000000000000073
W "real life" może i nie byłoby, ale procesor musi zaokrąglać i nie ma na to rady.

mhm.. fakt, przy bardzo dużej ilości liczb po zaokrągleniu wyjdzie inny wynik, niż powinien.

Niezupełnie. Nawet w tym prostym przypadku jeśli zrobi się porównanie:

[wynik] - 42 = 0

to już będzie fałszywe... Kwestia tego jaki źródłowy typ danych ma być brany pod uwagę (int czy numeric czy float...)

Dlatego napisałam "po zaokrągleniu" :)
czyli: round([wynik],0)-42 = 0

Dodam, że nawet przy wyniku 2,98572038125084E110 ta różnica to zero.Izabela Korzińska edytował(a) ten post dnia 08.01.09 o godzinie 13:18
Igor Piotr I.

Igor Piotr I. IT manager/Senior
Oracle Developer

Temat: SQL mnożenie kolejnych rekordów

super dziękuję wszystkim najbardziej podoba mi się User-Defined Aggregate
Grzegorz G.

Grzegorz G. ASE / Systems
Architect, Syniverse

Temat: SQL mnożenie kolejnych rekordów

Igor Piotr I.:
super dziękuję wszystkim najbardziej podoba mi się User-Defined Aggregate

Ano do takiego celu został stworzony :-)
Piotr Suszalski

Piotr Suszalski Freshmail Team
Leader / DBA

Temat: SQL mnożenie kolejnych rekordów

Można spróbować jeszcze czegoś takiego, też zadziała:

SET @i = 1;
SELECT @i:=(@i * id) as liczba FROM tablica;
Bartosz Ratajczyk

Bartosz Ratajczyk MS SQL Developer

Temat: SQL mnożenie kolejnych rekordów

Nie testowałem porównania z pomysłem Izabeli. Ja w SQL Serverze (2000) korzystam z

exp(sum(log(kolumna)))

gdzie log to logarytm naturalny.Bartosz Ratajczyk edytował(a) ten post dnia 29.01.09 o godzinie 09:21

konto usunięte

Temat: SQL mnożenie kolejnych rekordów

Chyba nie da się lepiej tego zrobić.

Z ciekawości poszukałem w tym kierunku i tutaj rezultat:
http://www.access.vis.pl/naworyta/funagreg.htm

Następna dyskusja:

Postgresql - porównywanie ...




Wyślij zaproszenie do