PostgreSQL 遞迴查詢應用場景

2021-09-17 23:53:17 字數 3372 閱讀 7231

今天在罈子裡有人提出了乙個問題,問題是這樣的:在以下指定表中

id name fatherid

1 中國 0

2 遼寧 1

3 山東 1

4 瀋陽 2

5 大連 2

6 濟南 3

7 和平區 4

8 沈河區 4

現在給定乙個id號,想得到它完整的名字。如:

當id=7時,名字是:中國遼寧瀋陽和平區

當id=5時,名字是:中國遼寧大連

id是任意給定的,不確定在哪一層。遞迴往上找,直到 fatherid=0 為止。也就是最高層級時結束,

求完整sql語句。

看到這個問題,第一想到的是可以用 pg的遞迴查詢實現,之前也寫過類似的例子,

但之前的例子

是向下遞迴,而這裡的需求是向上遞迴,略有不同,於是忍不住演示下:

這個問題的思路是分兩步走,第一步:查詢出指定節點的父節點;第二步:將查詢出的所有父節點排列到一行。

--1 建立測試表,並插入測試資料

skytf=> create table test_area(id int4,name varchar(32),fatherid int4);

create table

insert into test_area values (1, '中國' ,0);

insert into test_area values (2, '遼寧' ,1);

insert into test_area values (3, '山東' ,1);

insert into test_area values (4, '瀋陽' ,2);

insert into test_area values (5, '大連' ,2);

insert into test_area values (6, '濟南' ,3);

insert into test_area values (7, '和平區' ,4);

insert into test_area values (8, '沈河區' ,4);

skytf=> select * from test_area;

id | name | fatherid

----+--------+----------

1 | 中國 | 0

2 | 遼寧 | 1

3 | 山東 | 1

4 | 瀋陽 | 2

5 | 大連 | 2

6 | 濟南 | 3

7 | 和平區 | 4

8 | 沈河區 | 4

(8 rows)

--2 查詢指定節點以下的所有節點

with recursive r as ( 

select * from test_area where id = 4

union all

select test_area.* from test_area, r where test_area.fatherid = r.id

) select * from r order by id;

id | name | fatherid

----+--------+----------

4 | 瀋陽 | 2

7 | 和平區 | 4

8 | 沈河區 | 4

(3 rows)

備註:通常的用法是查詢指定節點以及指定節點以下的所有節點,那麼本貼的需求剛好相反,需要查詢指定節點以上的所有節點。

--3 查詢指定節點以上的所有節點

with recursive r as ( 

select * from test_area where id = 4

union all

select test_area.* from test_area, r where test_area.id = r.fatherid

) select * from r order by id;

id | name | fatherid

----+------+----------

1 | 中國 | 0

2 | 遼寧 | 1

4 | 瀋陽 | 2

(3 rows)

備註:這正是我們想要的結果,接下來需要將 name 字段結果集合並成一行,我這裡想到的是建立個 function,當然也有其它方法。

--4 create funcion

create or replace function func_get_area(in in_id int4, out o_area text)  as 

$$ declare

v_rec_record record;

begin

o_area = '';

for v_rec_record in (with recursive r as (select *

from test_area

where id = in_id

union all

select test_area.*

from test_area, r

where test_area.id = r.fatherid)select name

from r

order by id) loop

o_area := o_area || v_rec_record.name;

end loop;

return;

end;

$$language 'plpgsql';

備註:函式的作用為拼接 name 字段。

--5 測試

skytf=> select func_get_area(7) ;

func_get_area

--------------------

中國遼寧瀋陽和平區

(1 row)

skytf=> select func_get_area(5) ;

func_get_area

---------------

中國遼寧大連

(1 row)

備註:正好實現了需求,當表資料量較大時,考慮到效能,建議在表 test_area 字段 id,fatherid 上建立單獨的索引。

postgreSQL 遞迴查詢,使用陣列

遞迴查詢使用with recursive 陣列使用array 運用場景 用於統計多個層級中某乙個層級以及下面所有分類的資料 表結構 drop table if exists public test tree create table public test tree id int4 not null...

PostgreSQL遞迴查詢實現樹狀結構查詢

在postgresql的使用過程中發現了乙個很有意思的功能,就是對於需要類似於樹狀結構的結果可以使用遞迴查詢實現。比如說我們常用的公司部門這種資料結構,一般我們設計表結構的時候都是類似下面的sql,其中parent id為null時表示頂級節點,否則表示上級節點id。create table dep...

PostgreSQL遞迴查詢(從子到父 從父到子)

結語場景 資料庫中的資料存在父子關係 單繼承,每一條記錄只有乙個父記錄 如果要查詢一條記錄以及他的所有子記錄,或者要查詢一條記錄以及他的所有父記錄.那麼遞迴查詢就再合適不過了.可以簡化複雜的sql語句。現在資料庫有一張dictionary表,用於存放業務相關字典項 id,name,parent id...