PostgreSQL 务实应用(一/5)树形层级
项目中,经常会碰到多级的树形结构数据,如地区信息,省、市、区、街道等,或客户关系信息上三级,下三级等。
实际项目中,我们可能碰到以下两种需求:
- 一条记录中呈现路径:省 - 市 - 区 - 街道
- 一条记录中呈现上几级:上级,上上级,上上上级
此情此景,使用 WITH RECURSIVE 递归查询再合适不过。
递归查询
在介绍 WITH RECURSIVE 之前,我们先介绍一个 WITH
通过 WITH ,我们可以在写查询语句之前,为一个需要用到的子查询定义一个临时的别名,该别名可以查询语句中使用,从而简化查询语句。如下示例:
WITH 临时别名 AS(
SELECT 1 a, 2 b, 3 c
)
-- 下边是查询语句,像使用表或视图一样使用了“临时别名”
select a * a, b * b, c * c from 临时别名;
接下来我们再来看递归 RECURSIVE ,我们知道,递归形式上就是自己会调用自己,对于数据集而言,递归通常需要两个条件:
- 有入口数据,即递归开始的数据记录
- 有递归结束的条件,即在关联自己的同时有终止的条件
这第 2 点,原因很简单,关联自己产生的新数据记录又会成为递归关联中的数据。通常 WHERE 子句给出这个条件。
PostgreSQL 中,WITH RECURSIVE 即表示递归查询,“临时别名”在定义自身的子查询体中也可以使用。
我们来看一个示例:
-- 定义了一个临时别名 cet
WITH RECURSIVE cet AS (
-- 递归初始的数据,id=1, name="name 1", pid=null (最顶层父id为空)
SELECT 1 AS id, 'name 1' AS name, cast(null AS int) AS pid
UNION ALL
-- 联合 cet 自己,id 递增,结束条件为 id < 10。如果不加这个 WHERE 会如何?
SELECT id+1, 'name ' || (id+1), id FROM cet WHERE id < 10
)
SELECT * FROM cet;
输出以下结果:

搞定需求
上边的示例中的结果集就是一个典型的树形层级结构,我们以这个数据结果为例来完成文章开头提到的两个需求,首先我们把这个结果集变成一个视图以便当源数据用。
-- 创建一个名字为 view_tree_test 的视图
CREATE VIEW view_tree_test as
WITH RECURSIVE cet AS (
SELECT 1 AS id, 'name 1' AS name, cast(null AS int) AS pid
UNION ALL
SELECT id+1, 'name ' || (id+1), id FROM cet WHERE id < 10
)
SELECT * FROM cet;
我们以 view_tree_test 作为数据源来完成两大需求。
需求一,显示路径
WITH RECURSIVE tpath AS(
SELECT id, name, pid, name as path from view_tree_test where pid is null
UNION ALL
-- 联合子节点
SELECT a.id, a.name, a.pid,
tpath.path || '-' || a.name -- 父路径拼接当前节点名称形成路径
FROM view_tree_test a, tpath -- 关联已有结果,查询其子节点
WHERE a.pid = tpath.id
)
SELECT * FROM tpath;
查询结果可见其效果:

需求二,显示每第记录的上三级
WITH RECURSIVE uuup AS(
-- 初始值,顶层的上级均置为空,需要几级置几个空
SELECT id, name, '' 上级, '' 上上级, '' 上上上级 from view_tree_test where pid is null
UNION ALL
-- 联合子节点
SELECT a.id, a.name,
-- 父级即为上级,父的上级为上上级
uuup.name 上级, uuup.上级 上上级, uuup.上上级 上上上级
FROM view_tree_test a, uuup -- 关联已有结果,查询其子节点
WHERE a.pid = uuup.id
)
SELECT * FROM uuup;
顺利呈现相关的上三级,需要更多上级也是 SO EASY!

小结
PostgreSQL 提供了相当多实用的数据处理方式,让数据处理起来很是便捷。树形结构是应用中经常会使用到,使用递归查询能方便的处理跨层级的计算,还有很多想象空间哦。
PostgreSQL 务实应用(一/5)树形层级的更多相关文章
- PostgreSQL 务实应用(四/5)JSON
JSON 可谓风靡互联网,在数据交换使用上,其优势特别明显,其结构简洁.可读易读.形式灵活.很多 API 接口的数据都采用 JSON 来表示. PostgreSQL 对 JSON 提供了良好的支持.具 ...
- PostgreSQL 务实应用(五/5)常用表达
在实际应用中,对于具体的数据计算我们会找相应的函数来实现.而计算需求不同的表达,往往会使得我们使用不同的函数或方式来实现.或者也可以说,同一计算可以使用多种不同的表达方式实现. PostgreSQL ...
- PostgreSQL 务实应用(三/5)分表复制
问题的提出 在项目中,有些表的记录增长非常快,记录数过大时会使得查询变得困难,导致整个数据库处理性能下降.此时,我们会考虑按一定的规则进行分表存储. 常用的分表方式是按时间周期,如每月一张,每天一张等 ...
- 多层级Spinner列表选项实时更新树形层级(选择城市)
package com.example.spinnerdemo; import android.os.Bundle; import android.app.Activity; import andro ...
- PostgreSQL 务实应用(二/5)插入冲突
在项目中,有时会动态地按周期(如按月)封存统计数据,通常需要做这样的处理: 以按月封存为例,当月数据到达时,先需要检查该月是否有过记录,有则以更新的方式累加统计数字,无则添加一条记录. 假设我们创建以 ...
- 路径字符串数据转化为树型层级对象,path to json tree
由于项目中使用了react 及 ant-design ,在使用tree树型控件时,需要 类似下面的数据, const treeData = [{ title: '0-0', key: '0-0', c ...
- Python-模块
一.模块(modue)的概念: 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样, ...
- Java中的访问控制权限
简介 Java中为什么要设计访问权限控制机制呢?主要作用有两点: (1)为了使用户不要触碰那些他们不该触碰的部分,这些部分对于类内部的操作时必要的,但是它并不属于客户端程序员所需接口的一部分. (2) ...
- python--常见模块
本节大纲: 1.模块介绍 2.time&datetime 3.random. 4.os 5.sys 6.shutil 7.json&picle 8.shelve 9.xml处理 10. ...
随机推荐
- compute the su procedure time with python
#!/usr/bin/python2.6 import re,datetime file_name='sim.log' file=open(file_name,'r') acnum=[];time_r ...
- 提高sqlite 的运行性能(转载)
原文地址: https://blog.devart.com/increasing-sqlite-performance.html One the major issues a developer en ...
- static 静态域 类域 静态方法 工厂方法 he use of the static keyword to create fields and methods that belong to the class, rather than to an instance of the class 非访问修饰符
总结: 1.无论一个类实例化多少对象,它的静态变量只有一份拷贝: 静态域属于类,而非由类构造的实例化的对象,所有类的实例对象共享静态域. class Employee { private static ...
- EM算法索引
把这n个{试验结果来自B的概率}求和得到期望,平均后,得到B出正面的似然估计,同理有p和q. 重复迭代,直到收敛为止 http://blog.csdn.net/junnan321/article/de ...
- android中getWidth()和getMeasuredWidth()
getMeasuredWidth()获取的是view原始的大小,也就是这个view在XML文件中配置或者是代码中设置的大小.getWidth()获取的是这个view最终显示的大小,这个大小有可能等于原 ...
- windows server 2008 + IIS 7.5实现多用户FTP(多账号对应不同目录
在windows server 2003 + IIS 6 的时候,就已经能实现多用户FTP的功能,不过设置有写繁琐,如果站点多的话,设置账号.权限这些东西都要搞很久.Windows server 20 ...
- .cxx_destruct crash
开发过程中遇到 YXTBaseLabelCell .cxx_destruct崩溃,查了下,会在调用类的dealloc方法时调用cxx_destruct,于是看了下代码,找dealloc可能会崩溃的原因 ...
- php函数的参数引用变量
在php.ini中将allow_call_time_pass_reference的值改为'on'.
- vertical-align 的理解
1.vertical-align 属性和值列表
- python 特殊方法之new
object.__new__(cls[, ...]) Called to create a new instance of class cls. __new__() is a static metho ...