摘要:今天在壇子里有人提出了一個問題,問題是這樣的在以下指定表中中國遼寧山東沈陽大連濟南和平區(qū)沈河區(qū)現(xiàn)在給定一個號,想得到它完整的名字。遞歸往上找,直到為止。也就是最高層級時結(jié)束,求完整語句。
今天在壇子里有人提出了一個問題,問題是這樣的:在以下指定表中
id name fatherid
1 中國 0
2 遼寧 1
3 山東 1
4 沈陽 2
5 大連 2
6 濟南 3
7 和平區(qū) 4
8 沈河區(qū) 4
現(xiàn)在給定一個id號,想得到它完整的名字。如:
當(dāng)id=7時,名字是:中國遼寧沈陽和平區(qū)
當(dāng)id=5時,名字是:中國遼寧大連
id是任意給定的,不確定在哪一層。遞歸往上找,直到 fatherid=0 為止。也就是最高層級時結(jié)束,
求完整SQL語句。
看到這個問題,第一想到的是可以用 PG的遞歸查詢實現(xiàn),之前也寫過類似的例子,
http://francs3.blog.163.com/b...,但之前的例子
是向下遞歸,而這里的需求是向上遞歸,略有不同,于是忍不住演示下:
這個問題的思路是分兩步走,第一步:查詢出指定節(jié)點的父節(jié)點;第二步:將查詢出的所有父節(jié)點排列到一行。
--1 創(chuàng)建測試表,并插入測試數(shù)據(jù)
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, "和平區(qū)" ,4); insert into test_area values (8, "沈河區(qū)" ,4); skytf=> select * From test_area; id | name | fatherid ----+--------+---------- 1 | 中國 | 0 2 | 遼寧 | 1 3 | 山東 | 1 4 | 沈陽 | 2 5 | 大連 | 2 6 | 濟南 | 3 7 | 和平區(qū) | 4 8 | 沈河區(qū) | 4 (8 rows)
--2 查詢指定節(jié)點以下的所有節(jié)點
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 | 和平區(qū) | 4 8 | 沈河區(qū) | 4 (3 rows)
備注:通常的用法是查詢指定節(jié)點以及指定節(jié)點以下的所有節(jié)點,那么本貼的需求剛好相反,需要查詢指定節(jié)點以上的所有節(jié)點。
--3 查詢指定節(jié)點以上的所有節(jié)點
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)
備注:這正是我們想要的結(jié)果,接下來需要將 name 字段結(jié)果集合并成一行,我這里想到的是創(chuàng)建個 function,當(dāng)然也有其它方法。
--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";
備注:函數(shù)的作用為拼接 name 字段。
--5 測試
skytf=> select func_get_area(7) ; func_get_area -------------------- 中國遼寧沈陽和平區(qū) (1 row) skytf=> select func_get_area(5) ; func_get_area --------------- 中國遼寧大連 (1 row)
備注:正好實現(xiàn)了需求,當(dāng)表數(shù)據(jù)量較大時,考慮到性能,建議在表 test_area 字段 id,fatherid 上建立多帶帶的索引。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/38974.html
摘要:先聲明,瞎猜的,個人理解,不一定對。重復(fù)執(zhí)行步驟和,只是這里執(zhí)行第步的時候,從中選出的記錄為執(zhí)行第步,就變成了,就變成了找的兒子記錄如果第步返回多條記錄,類似啦,反正遞歸嘛如此,自頂向下,一棵樹就出來了 先聲明,瞎猜的,個人理解,不一定對。 遞歸查詢大家都知道,常見的如一張表,包含id(主鍵),parent_id(該記錄的父親id),比如我們要從某1個id往下找他所有的兒子還有孫子(這...
摘要:相比自建,其可靠性更高,方便運維維護。宋體經(jīng)過審慎考慮,用戶同時選用三種數(shù)據(jù)庫,針對性的滿足不同目標(biāo)。宋體宋體其中,相比于在上的快速高效是其優(yōu)勢,也是用戶選型的重要砝碼。PostgreSQL UDB用在大數(shù)據(jù)分析上,查詢效率更高。相比自建,其可靠性更高,方便運維維護。 — 31會議運維經(jīng)理 湯雷 如何用好PostgreSQL? PostgreSQL是業(yè)內(nèi)一款十分流行的開源數(shù)...
摘要:這可以通過負(fù)載平衡來實現(xiàn)數(shù)據(jù)分片當(dāng)問題不是并發(fā)查詢的數(shù)量,而是數(shù)據(jù)庫的大小和單個查詢的速度時,可以實現(xiàn)不同的方法。 showImg(https://segmentfault.com/img/remote/1460000018875091); 來源 | 愿碼(ChainDesk.CN)內(nèi)容編輯 愿碼Slogan | 連接每個程序員的故事 網(wǎng)站 | http://chaindesk.cn...
閱讀 1734·2021-11-18 10:02
閱讀 2243·2021-11-15 11:38
閱讀 2695·2019-08-30 15:52
閱讀 2219·2019-08-29 14:04
閱讀 3255·2019-08-29 12:29
閱讀 2109·2019-08-26 11:44
閱讀 1023·2019-08-26 10:28
閱讀 862·2019-08-23 18:37