我已经制定了一个大的PG / SQL程序来实现这个目标:
基于此"数据"表:
order | product
----------------
1 | A
1 | B
2 | A
2 | D
3 | A
3 | C
4 | A
4 | B
5 | Y
5 | Z
6 | W
6 | A
7 | A
我正在建立这张桌子:" DICO"
order | couple | first | second
-------------------------------
1 | A-B | A | B
2 | A-D | A | D
3 | A-C | A | C
4 | A-B | A | B
5 | Y-Z | Y | Z
6 | W-A | W | A
当我完全计算了这个dico表时(在DATA中可能需要超过一天的3.000.000行),我在桌子上做了一个请求,以便最好的情况发生:
order | count | total1stElem | %1stElem | total2ndElem | %2ndElem
------------------------------------------------------------------
A-B | 2 | 6 | 33% | 2 | 100%
A-D | 1 | 6 | 16% | 1 | 100%
A-C | 1 | 6 | 16% | 1 | 100%
Y-Z | 1 | 1 | 100% | 1 | 100%
W-A | 1 | 1 | 100% | 6 | 16%
所以它的工作非常好,但我显然需要一种更好的表现方式:我认为它可以直接用一个好的(和大的)请求。我不知道是否有必要建立DICO表......!
这是大PG / SQL脚本:
-- Function: addinparamsales()
-- DROP FUNCTION addinparamsales();
CREATE OR REPLACE FUNCTION addinparamsales()
RETURNS trigger AS
$BODY$
DECLARE
productstab varchar(14) [];
coupletabarray varchar(50) [];
couplearrayTMP varchar(14) [];
couplevarcharconcat varchar(29);
v_allcmd data1%rowtype;
v_allproductincmd data1%rowtype;
v_alldico dico1%rowtype;
v_count_dico1 bigint;
v_total_dico1 bigint;
v_iterator_dico1 bigint;
v_count_integer bigint;
v_count1 bigint;
i bigint;
v_test varchar[];
v_test2 varchar(14)[];
tab_result varchar[];
items RECORD;
r record;
first varchar(50);
second varchar(50);
BEGIN
IF (TG_OP = 'INSERT') THEN
TRUNCATE dico1;
i = 0 ;
FOR v_allcmd
IN
SELECT d.documentsourceid FROM data1 d GROUP BY d.documentsourceid ORDER BY d.documentsourceid ASC
LOOP
productstab := null;
FOR v_allproductincmd
IN
SELECT * FROM data1 d WHERE d.documentsourceid = v_allcmd.documentsourceid ORDER BY documentsourceid ASC, productid ASC
LOOP
productstab := array_append(productstab, v_allproductincmd.productid);
END LOOP;
FOR i IN 1 .. array_upper(productstab, 1)
LOOP
coupletabarray := array_append(coupletabarray,productstab[i]);
END LOOP;
FOR v_test2
IN
SELECT * FROM "twouplets"(coupletabarray) ORDER BY twouplets DESC
LOOP
IF array_length(v_test2,1) IS NOT NULL -- not empty array
THEN
FOR i IN 1 .. array_length(v_test2,1)
LOOP
couplearrayTMP := array_append(couplearrayTMP,v_test2[i]);
END LOOP;
FOR i IN 1 .. array_length(couplearrayTMP,1)
LOOP
IF i = 1 THEN
couplevarcharconcat := CONCAT(couplearrayTMP[i]);
first := couplearrayTMP[i];
ELSE
couplevarcharconcat := CONCAT(couplevarcharconcat,'|',couplearrayTMP[i]);
second := couplearrayTMP[i];
END IF ;
END LOOP;
INSERT INTO dico1 (documentsourceid, couple,first, second) VALUES (v_allcmd.documentsourceid,couplevarcharconcat, first, second);
couplevarcharconcat := null;
couplearrayTMP := null;
END IF;
END LOOP;
coupletabarray := null;
END LOOP;
END IF;
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION addinparamsales()
OWNER TO postgres;
有人有一些想法来改进这个程序吗?例如,使用请求而不是这个大的PG / SQL过程吗?