今天在罈子裡有人提出了乙個問題,問題是這樣的:在以下指定表中
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...