mam tabelę numery:
Kod
test=# \d numery
Table "public.numery"
Column | Type | Modifiers
--------+---------+-----------------------------------------------------
id | integer | not null default nextval('numery_id_seq'::regclass)
numer | integer |
grupa | integer |
Table "public.numery"
Column | Type | Modifiers
--------+---------+-----------------------------------------------------
id | integer | not null default nextval('numery_id_seq'::regclass)
numer | integer |
grupa | integer |
w której mam dane:
Kod
test=# select * from numery;
id | numer | grupa
----+-------+-------
1 | 1 | 1
2 | 1 | 1
3 | 1 | 1
4 | 1 | 1
5 | 1 | 1
6 | 1 | 1
7 | 1 | 1
8 | 1 | 1
9 | 3 | 1
10 | 3 | 1
11 | 10 | 2
12 | 10 | 2
13 | 10 | 2
14 | 10 | 2
15 | 10 | 2
16 | 8 | 2
17 | 8 | 2
18 | 8 | 2
19 | 7 | 2
20 | 8 | 3
21 | 8 | 3
22 | 8 | 3
23 | 8 | 3
24 | 8 | 3
(24 rows)
id | numer | grupa
----+-------+-------
1 | 1 | 1
2 | 1 | 1
3 | 1 | 1
4 | 1 | 1
5 | 1 | 1
6 | 1 | 1
7 | 1 | 1
8 | 1 | 1
9 | 3 | 1
10 | 3 | 1
11 | 10 | 2
12 | 10 | 2
13 | 10 | 2
14 | 10 | 2
15 | 10 | 2
16 | 8 | 2
17 | 8 | 2
18 | 8 | 2
19 | 7 | 2
20 | 8 | 3
21 | 8 | 3
22 | 8 | 3
23 | 8 | 3
24 | 8 | 3
(24 rows)
chcę teraz znaleźć dominantę (czyli wartość najcześciej się pojawiająca w grupie) dla każdej z grup, czyli aby wynik zapytania wylądał mniej więcej tak:
Kod
test=# select domin(numer), grupa from numery group by grupa;
domin | grupa
-------+-------
8 | 3
10 | 2
1 | 1
(3 rows)
domin | grupa
-------+-------
8 | 3
10 | 2
1 | 1
(3 rows)
trafiłem na stronę 34.10. User-Defined Aggregates i tam po części jest napisane jak tworzyć własne funkcje agregujące, niestety nie mam pojęcia jak stworzyć funkcję wyliczającą dominantę.
Robił ktoś własne metody agregujące?
Pozdrawiam
w pocie czoła... ale działa... nie chciało mi się ani "wyczyścić" z niepotrzebnych części kodu ani go optymalizować, może komuś się przyda to przyda, nic nie gwarantuję bo nie czuję się w tym języku dobrze...
Kod
CREATE OR REPLACE FUNCTION dominanta("input" anyarray)
RETURNS integer AS
$BODY$DECLARE
tmp integer[][];
arr integer[][];
ret integer;
firstRes integer;
tmpInt integer;
arrCount integer;
tmpCount integer;
found boolean;
BEGIN
ret := 0;
-- array_upper(array, 1) zwraca count(array)
arrCount := array_upper($1, 1);
FOR i IN 1..arrCount LOOP
-- aktualna wartosc w tablicy dla iteracji
tmpInt := getArrayElem($1, i);
found := false;
IF tmp[1][1] IS NULL
THEN
tmpCount := 0;
ELSE
tmpCount := array_upper(tmp, 1);
END IF;
FOR j IN 1..tmpCount LOOP
IF tmp[j][1] = tmpInt
THEN
tmp[j][2] := tmp[j][2] + 1;
found := true;
EXIT;
END IF;
END LOOP;
IF found = false
THEN
tmp := tmp || ARRAY[[tmpInt, 1]];
END IF;
END LOOP;
tmpInt := 0;
FOR i IN 1..array_upper(tmp, 1) LOOP
IF tmpInt < tmp[i][2]
THEN
ret := tmp[i][1];
tmpInt := tmp[i][2];
END IF;
END LOOP;
RETURN ret;
END;$BODY$
LANGUAGE 'plpgsql' IMMUTABLE STRICT;
RETURNS integer AS
$BODY$DECLARE
tmp integer[][];
arr integer[][];
ret integer;
firstRes integer;
tmpInt integer;
arrCount integer;
tmpCount integer;
found boolean;
BEGIN
ret := 0;
-- array_upper(array, 1) zwraca count(array)
arrCount := array_upper($1, 1);
FOR i IN 1..arrCount LOOP
-- aktualna wartosc w tablicy dla iteracji
tmpInt := getArrayElem($1, i);
found := false;
IF tmp[1][1] IS NULL
THEN
tmpCount := 0;
ELSE
tmpCount := array_upper(tmp, 1);
END IF;
FOR j IN 1..tmpCount LOOP
IF tmp[j][1] = tmpInt
THEN
tmp[j][2] := tmp[j][2] + 1;
found := true;
EXIT;
END IF;
END LOOP;
IF found = false
THEN
tmp := tmp || ARRAY[[tmpInt, 1]];
END IF;
END LOOP;
tmpInt := 0;
FOR i IN 1..array_upper(tmp, 1) LOOP
IF tmpInt < tmp[i][2]
THEN
ret := tmp[i][1];
tmpInt := tmp[i][2];
END IF;
END LOOP;
RETURN ret;
END;$BODY$
LANGUAGE 'plpgsql' IMMUTABLE STRICT;
Pozdrawiam
Cezar708