1. 程式人生 > >PostgreSql遞迴包含層級level

PostgreSql遞迴包含層級level

當在用oracle做遞迴時,往往會用到一個虛列level,表示當前的節點是第幾層,現在PostgreSql的遞迴語法中(with recursive)中不包含層級列,當然你安裝了PostgreSql的擴充套件也是可以的,就是安裝cross這個指令碼,具體在postgreSql安裝目錄項的share/extension下的tablefunc.sql,指令碼。

由於在我實際的專案中不允許安裝哪些指令碼,因此只能先自定義一個函式,具體程式碼如下:

首先,建立自定義型別

CREATE TYPE public.type_custom_recursive AS (
  keyid TEXT,
  branch TEXT,
  parent_keyid TEXT,
  level TEXT
);

再建立函式:

CREATE OR REPLACE FUNCTION public.custom_recursive (
  table_name varchar,
  keyid text,
  parent_keyid text,
  keyid_value text,
  level integer,
  split_value varchar
)
RETURNS SETOF public.type_custom_recursive AS
$body$
declare
test_ type_custom_recursive;
    sql_text VARCHAR(1000);


BEGIN
-- i_id  as keyid,id as branch,level as level 
if $5 = 0 THEN
sql_text := 'select i_id::text as keyid,id::text as branch,i_parent_id::text as parent_keyid,level::text as level from (  
          with recursive temp as(
          select '||$2||' as i_id,'||$2||'::text as id ,'||$3||' from '|| $1 ||' where '||$2||' = cast('||$4||
          'as int) union all
          select b.'||$2||',cast (a.id || '''||split_value||''' || b.'||$2||' as text) as id,b.'||$3||'  from temp a,'||$1||' b
          where a.'||$2||' = b.'||$3||')select i_id,id,f_char_in_string(id,'''||$6||''')+1 as level,i_parent_id from temp
          ) t order by i_id';
          
else
sql_text := 'select i_id::text as keyid,id::text as branch,i_parent_id::text as parent_keyid,level::text as level from (  
          with recursive temp as(
          select '||$2||' as i_id,'||$2||'::text as id ,'||$3||' from '|| $1 ||' where '||$2||' = cast('||$4||
          'as int) union all
          select b.'||$2||',cast (a.id || '''||split_value||''' || b.'||$2||' as text) as id,b.'||$3||'  from temp a,'||$1||' b
          where a.'||$2||' = b.'||$3||')select i_id,id,f_char_in_string(id,'''||$6||''')+1 as level,i_parent_id from temp
          ) t  where level = '|| $5 ||' order by i_id';          
end if;


 for test_ in execute sql_text loop
          return next test_;
  end loop;          
end;
$body$
LANGUAGE 'plpgsql'

;

說明:

table_name varchar ,--需要遞迴的表名
  keyid text,--id
  parent_keyid text,--父id
  keyid_value text,--id的值
  level integer,--層級 0的話顯示當前id下的所有節點
  split_value varchar --  分隔符比如"->"

注意這裡的id預設都是為整型的,如果id是varchar型那麼需要稍作修改的。

下面做個小例:

select * from custom_recursive('organization','i_id','i_parent_id','1',0,'->');

輸出為

keyid,branch,parentkeyid,level

1 ,1,null,1

2,1->2,1,2

3,1->3,1,2