|
再改写一下,就不要求CUST_ID是连续的了:
DECLARE
i int;
TYPE t_num IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
parents t_num;
ranks t_num;
lv_id t_num;
lv_gid t_num;
parentX int;
parentY int;
rankX int;
rankY int;
last_phone int;
FUNCTION f_find_parent(p_cur_cust IN INTEGER) RETURN INTEGER
AS
parent int;
BEGIN
parent := parents(p_cur_cust);
IF parent <> p_cur_cust THEN
parent := f_find_parent(parent);
parents(p_cur_cust) := parent;
END IF;
RETURN parent;
END f_find_parent;
BEGIN
SELECT id BULK COLLECT INTO lv_id from cust ORDER BY id;
FOR i IN 1..lv_id.COUNT LOOP
ranks(lv_id(i)) := 0;
parents(lv_id(i)):=lv_id(i);
END LOOP;
last_phone :=0;
-- union
FOR cur IN (select id, phone_num from phone order by phone_num, id) LOOP
if cur.phone_num <> last_phone then
-- find parent for x
parentX := f_find_parent(cur.id);
rankX := ranks(parentX);
last_phone := cur.phone_num;
CONTINUE;
END IF;
-- find parent for y
parentY := f_find_parent(cur.id);
rankY := ranks(parentY);
CASE
WHEN parentX = parentY THEN
continue;
WHEN rankX < rankY THEN
parents(parentX) := parentY;
WHEN rankX > rankY THEN
parents(parentY) := parentX;
WHEN rankX = rankY THEN
parents(parentY) := parentX;
ranks(parentX) := rankX+1;
END CASE;
END LOOP;
-- find for each cust
FOR i IN 1..lv_id.count LOOP
lv_gid(i) := f_find_parent(lv_id(i));
END LOOP;
FORALL i IN 1..lv_id.count
UPDATE cust SET gid=lv_gid(i) WHERE id=lv_id(i);
END;
/
|
|