http://www.postgresonline.com/journal/archives/131-Using-Recursive-Common-table-expressions-to-represent-Tree-structures.html

Tree Problem and was based on PostgreSQL 7.4 technology.

We'll repeat the text here for completeness and demonstrate the PostgreSQL 8.4 that solves this and more efficiently.

The Problem

Suppose you are tracking supplies and have a field called si_item and
another called si_parentid.
The parent keeps track of what subclass a supply item belongs to. E.g.
you have paper parent that has subclasses such as recycled,
non-recycled. When someone takes supplies, you want to return the fully
qualified name e.g. Paper->Recycled->20 Lb

Below is what the structure of your table looks like.

si_id int, si_parentid int, si_item. In your table are the following entries

si_id si_parentid si_item
1   Paper
2 1 Recycled
3 2 20 lb
4 2 40 lb
5 1 Non-Recycled
6 5 20 lb
7 5 40 lb
8 5 Scraps

Solution

CREATE TABLE supplyitem(si_id integer PRIMARY KEY, si_parentid integer, si_item varchar(100));

--load up the table (multirow constructor introduced in 8.2)
INSERT INTO supplyitem(si_id,si_parentid, si_item)
VALUES (1, NULL, 'Paper'),
(2,1, 'Recycled'),
(3,2, '20 lb'),
(4,2, '40 lb'),
(5,1, 'Non-Recycled'),
(6,5, '20 lb'),
(7,5, '40 lb'),
(8,5, 'Scraps'); --Recursive query (introduced in 8.4 returns fully qualified name)
WITH RECURSIVE supplytree AS
(SELECT si_id, si_item, si_parentid, CAST(si_item As varchar(1000)) As si_item_fullname
FROM supplyitem
WHERE si_parentid IS NULL
UNION ALL
SELECT si.si_id,si.si_item,
si.si_parentid,
CAST(sp.si_item_fullname || '->' || si.si_item As varchar(1000)) As si_item_fullname
FROM supplyitem As si
INNER JOIN supplytree AS sp
ON (si.si_parentid = sp.si_id)
)
SELECT si_id, si_item_fullname
FROM supplytree
ORDER BY si_item_fullname;

Result looks like

si_id |      si_item_fullname
------+-----------------------------
1 | Paper
5 | Paper->Non-Recycled
6 | Paper->Non-Recycled->20 lb
7 | Paper->Non-Recycled->40 lb
8 | Paper->Non-Recycled->Scraps
2 | Paper->Recycled
3 | Paper->Recycled->20 lb
4 | Paper->Recycled->40 lb

Trackbacks
Social comments and analytics for this post
This post was mentioned on Twitter by roblb: Using Recursive
Common table expressions to represent Tree structures: A very long time
ago, we wrote .. http://bit.ly/Flne3 #postgres
Weblog: uberVU - social comments
Tracked: Jan 04, 21:19

Weblog: www.postgresonline.com
Tracked: Aug 20, 00:58

Comments
Display comments as
(Linear | Threaded)
Great topic!

A couple of observations:

* Unless the length 1000 has some significance, use TEXT instead of
VARCHAR(1000).

* It might well be both faster and more correct to push items into an array
and use array_to_string() in the outer SELECT, and it won't be subject to
sorting anomalies.

WITH RECURSIVE supplytree AS
(
SELECT
si_id,
si_item,
si_parentid,
ARRAY[si_item] AS si_item_array
FROM supplyitem
WHERE si_parentid IS NULL
UNION ALL
SELECT
si.si_id,si.si_item,
si.si_parentid,
sp.si_item_array || si.si_item As si_item_array
FROM
supplyitem As si
JOIN
supplytree AS sp
ON (si.si_parentid = sp.si_id)
)
SELECT
si_id,
array_to_string(si_item_array, '->') AS si_item_fullname
FROM supplytree
ORDER BY si_item_array;

#1

David Fetter

(Homepage)
on
2009-08-16 19:10

Have thought about using ltree ?

http://www.postgresql.org/docs/current/static/ltree.html

I'am not saying than WITH RECURSIVE is bad .. just that, there are simpler solution sometimes ;-)

#2

Arek

on
2009-09-19 18:16

Good point. We haven't explored the use of ltree so
will have to give it a test drive sometime. I think the only thing
against it is that its a PostgreSQL specific feature where as the CTE is
more ANSI portable (except for possiblyt the word RECURSIVE)
#2.1

Leo

on
2009-09-28 02:58

How do you use it to find the parent path for just a single item?
#3

sabra

on
2009-09-26 18:35

Sabra,

Couple of ways -- you could write a function as we demonstrated in
linked article, but that is not as suitable for multiple sets since it
would probably do a subquery for each record.

You coulde also take our example and limit with a WHERE clause but that is much slower than it could be.

The other way would be to recurse backward from the child to the parent.
So instead of starting at parent nodes -- you start at the child node
and keep on unioning until you hit a parent with no parent. Will have
to write that up sometime.

#3.1

Leo

on
2009-09-28 03:05

many thanks for this great example.i implemented the child to parent recursion in case someone needs it:

--Recursive query (introduced in 8.4 returns fully qualified name)
WITH RECURSIVE supplytree AS
(SELECT si_id, si_item, si_parentid, CAST(si_item As varchar(1000)) As si_item_fullname
FROM supplyitem
WHERE si_item in( '40 lb')
UNION ALL
SELECT si.si_id,si.si_item,
si.si_parentid,
CAST(si.si_item || '->' || sp.si_item_fullname As varchar(1000)) As si_item_fullname
FROM supplyitem As si
INNER JOIN supplytree AS sp
ON (si.si_id = sp.si_parentid)
)
SELECT si_id, si_item_fullname
FROM supplytree where si_parentid is null
ORDER BY si_item_fullname;

#4

krishnen

on
2010-02-16 15:24

Great example for recursive CTE. Very useful. Thanks!
#5

Shirish

on
2010-09-30 11:05

this is most easy

table tema
-field tema_id (is the identificator)
-field nombre (is the name)
-field padre_id (is the parent id)

WITH RECURSIVE tema_tree AS (
SELECT tema_id, nombre, padre_id, nombre||'' full_name
FROM tema
WHERE padre_id IS NULL
UNION ALL
SELECT t.tema_id, t.nombre, t.padre_id, tt.full_name||' -> '||t.nombre full_name
FROM tema t
JOIN tema_tree tt ON t.padre_id = tt.tema_id
)
SELECT tema_id, full_name
FROM tema_tree
ORDER BY 2

#6

vakan

(Homepage)
on
2011-01-13 16:14

Using Recursive Common table expressions to represent Tree structures的更多相关文章

  1. PostgreSQL: WITH Queries (Common Table Expressions)

    WITH 允许在 SELECT 语句中定义"表"的表达式,这个"表"的表达式称之为"公共表表达式(Common Table Expression)&q ...

  2. The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP or FOR XML is also specified.

    https://stackoverflow.com/questions/30045871/sorting-the-view-based-on-frequency-in-sql-server Just ...

  3. Common Table Expressions (CTE)

    子查询有时使用起来很麻烦,因为所有的过滤和匹配逻辑都必须集成到子查询表达式中.如果只需要执行一个任务,且只需要使用一次杳询表达式,子查询是很好的选择.但子查询不能被重用,也不能很好地支持多个需求.这个 ...

  4. leetcode 235. Lowest Common Ancestor of a Binary Search Tree 236. Lowest Common Ancestor of a Binary Tree

    https://www.cnblogs.com/grandyang/p/4641968.html http://www.cnblogs.com/grandyang/p/4640572.html 利用二 ...

  5. 【LeetCode】236. Lowest Common Ancestor of a Binary Tree

    Lowest Common Ancestor of a Binary Tree Given a binary tree, find the lowest common ancestor (LCA) o ...

  6. CTE(Common Table Expression) 公用表表达式

    在编写T-SQL代码时,往往需要临时存储某些结果集.前面我们已经广泛使用和介绍了两种临时存储结果集的方法:临时表和表变量.除此之外,还可以 使用公用表表达式的方法.公用表表达式(Common Tabl ...

  7. Leetcode之236. Lowest Common Ancestor of a Binary Tree Medium

    236. Lowest Common Ancestor of a Binary Tree Medium https://leetcode.com/problems/lowest-common-ance ...

  8. 88 Lowest Common Ancestor of a Binary Tree

    原题网址:https://www.lintcode.com/problem/lowest-common-ancestor-of-a-binary-tree/description 描述 给定一棵二叉树 ...

  9. 【刷题-LeetCode】236. Lowest Common Ancestor of a Binary Tree

    Lowest Common Ancestor of a Binary Tree Given a binary tree, find the lowest common ancestor (LCA) o ...

随机推荐

  1. Redis和Memcached的区别详解

    转载于:http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/119.html?1455855360 Redis的作者Salvatore ...

  2. Java构造函数

    构造函数的定义: 构造函数 ,是一种特殊的方法.主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中.特别的一个类可以有多个构造函数 ,可根据其参数个 ...

  3. Atitit 数据存储的数据表连接attilax总结

    Atitit 数据存储的数据表连接attilax总结 1.1. 三种物理连接运算符:嵌套循环连接.合并连接以及哈希连接1 1.2. a.嵌套循环连接(nested loops join)1 1.3. ...

  4. paip. 解决php 以及 python 连接access无效的参数量。参数不足,期待是 1”的错误

    paip. 解决php 以及 python 连接access无效的参数量.参数不足,期待是 1"的错误 作者Attilax  艾龙,  EMAIL:1466519819@qq.com  来源 ...

  5. chrome调试本地项目, 引用本地javascript文件

    chrome调试本地项目, 引用本地javascript文件 本地文件可以访问本地文件 修改快捷方式属性 C:\Users\xxx\AppData\Local\Google\Chrome\Applic ...

  6. IOS-各控件默认尺寸和参考图标大小

    UITabBar

  7. XML学习笔记3——XSD简述

    现在的语言,如果不有那么一点OO的影子,都不好意思称之为语言了.在XML的语义约束方面,DTD虽然简单,但是功能不够强大,完全是直白的描述,于是又有了替代DTD的XSD(XML Schema Defi ...

  8. iOS开发中 workspace 与 static lib 工程的联合使用

    在iOS开发中,其实workspace的使用没有完全发挥出来,最近做了一些研究,也想把之前写过的代码整理下,因为iOS里面的布局方式,交互方式也就那么几种.所以,整理好了之后,更能快捷开发,而且能够形 ...

  9. CSS中常见的6种文本样式

    前面的话 CSS文本样式是相对于内容进行的样式修饰.由于在层叠关系中,内容要高于背景.所以文本样式相对而言更加重要.有些人对文本和字体样式之间的不同不太了解,简单地讲,文本是内容,而字体则用于显示这个 ...

  10. Linux下如何删除Oracle

    一. 停止Oracle数据库服务 shutdown immediate 二. 停止监听服务 lsnrctl stop 三. 用dbca卸载数据库实例 四. 删除相关文件  -->> 如果只 ...