SQL-递归查询在Ora与Mssql
今天在工作中,有同事“请教”从 Sql Server 移植数据到 DM DB 的改写问题,本以为难度不大,结果发现 Sql Server 数据库的语法、架构上,与 Oracle / DM 数据库差异还是蛮大的,弄得没怎么用过 Sql Server 的我十分头大,赶紧记载一些工作中遇到的问题,也加固 SQL 的学习,像递归查询这个问题,对我来说一直都是一个比较生涩的点。
在 Mssql 中,递归的语法是用 With 来实现的,所以一开始我还以为是要用 With 生成临时结果来处理,后来在网上查找了一下资料,才知道语法就是这样的。可以参考 TurboWay 博客(https://www.cnblogs.com/TurboWay/p/7728746.html)中的说法,于是我在笔记本上装了一个 Sql Server 2017 进行测试,为了方便,就采用了博客中的脚本进行测试。
/*
test表
ID 地区ID
Name 地区名称
Main_ID 地区所属上级ID
Sign 地区等级 例如:福建-厦门-湖里 分别是 1,2,3
*/
-- 建表
SELECT 1003 ID, '福建' Name, 0 Main_ID, 1 Sign INTO test union all
SELECT 1050 , '福州' , 1003 , 2 union all
SELECT 1051 , '厦门' , 1003 , 2 union ALL
SELECT 1375 , '思明' , 1051 , 3 union all
SELECT 1382 , '海沧' , 1051 , 3 union all
SELECT 1381 , '湖里' , 1051 , 3 union all
SELECT 1374 , '集美' , 1051 , 3 union all
SELECT 1373 , '同安' , 1051 , 3 union all
SELECT 1380 , '翔安' , 1051 , 3 union ALL
SELECT 667582720122 , '鼓楼' , 1050 , 3 union all
SELECT 667582725528 , '台江' , 1050 , 3 union all
SELECT 667582729587 , '仓山' , 1050 , 3 union all
SELECT 667582732602 , '马尾' , 1050 , 3 union all
SELECT 667582735385 , '晋安' , 1050 , 3 union all
SELECT 667582738507 , '闽侯' , 1050 , 3 union all
SELECT 667582742586 , '连江' , 1050 , 3 union all
SELECT 667582745634 , '罗源' , 1050 , 3 union all
SELECT 667582748358 , '闽清' , 1050 , 3 union all
SELECT 667582751824 , '永泰' , 1050 , 3 union all
SELECT 667582755215 , '平潭' , 1050 , 3 union all
SELECT 667582760309 , '福清' , 1050 , 3 union all
SELECT 667582764565 , '长乐' , 1050 , 3;
这里才发现,在 Mssql 中,可以通过这样创建表,有点类似 Oracle 语法中的 Create Table as Select 的方式。通过导出 DDL 可以看到表 test 中列的精度。
CREATE TABLE [dbo].[test](
[ID] [numeric](12, 0) NOT NULL,
[Name] [varchar](4) NOT NULL,
[Main_ID] [int] NOT NULL,
[Sign] [int] NOT NULL
) ON [PRIMARY]
GO
发现 number 类型和 varchar 类型,都是刚好是 id 列和 name 列的最大精度。表环境拟好以后,可以执行 SQL。
WITH CTE AS
(
--父项
SELECT a.*,1 level
FROM test a WHERE ID=1003
UNION ALL
--递归结果集中的下级
SELECT a.* , level + 1 as level
FROM test a
INNER JOIN CTE b ON b.ID=a.Main_ID
)select * from CTE; --结果集
ID Name Main_ID Sign level
--------------------------------------- ---- ----------- ----------- -----------
1003 福建 0 1 1
1050 福州 1003 2 2
1051 厦门 1003 2 2
1375 思明 1051 3 3
1382 海沧 1051 3 3
1381 湖里 1051 3 3
1374 集美 1051 3 3
1373 同安 1051 3 3
1380 翔安 1051 3 3
667582720122 鼓楼 1050 3 3
667582725528 台江 1050 3 3
667582729587 仓山 1050 3 3
667582732602 马尾 1050 3 3
667582735385 晋安 1050 3 3
667582738507 闽侯 1050 3 3
667582742586 连江 1050 3 3
667582745634 罗源 1050 3 3
667582748358 闽清 1050 3 3
667582751824 永泰 1050 3 3
667582755215 平潭 1050 3 3
667582760309 福清 1050 3 3
667582764565 长乐 1050 3 3
其实,从这个结果集就很好理解递归查询应用场景,以地点这个场景来解释层次查询是非常适合的,如果表中没有 Sign 这个列,在 Sql 中的 level 也能非常好的分层。第一层就是福建,福建下面的第二层地点就是福州和厦门, Sign = 3 的就是第三层地名。把它们关联起来的是Id 与 Main_id ,一般我们把 Main_id 叫 Parent id ,即它的父节点 id 。比如地点马尾,它的 Main_id 是1050,而 id 是1050的就是马尾的父节点——福州。如果我们把整个结果集当成一棵树的结构的话,在以上 Sql 中,是从 id = 1003 开始,遍历整棵树,Sign = 1 是根的话,Sign = 3 的就是这棵树的叶,这样的查询就是自顶向下(树形结构是倒着的)的一种层次查询。(仅个人理解,可能不准确)
而下面这样,就是自底向上的查询了,通过一个叶子节点去查找父节点。也很好理解,第一部分先获取到叶子节点的 id,第二部分,通过已经查到的叶子节点数据(cte as b)的父节点,来找父节点的数据(b.Main_id = test.id)。
with cte as (
select a.*,1 as level from test a where id = 667582751824
union all
select a.*,level + 1 as level from test a inner join cte as b
on a.id = b.Main_ID
) select * from cte; --结果集
ID Name Main_ID Sign level
--------------------------------------- ---- ----------- ----------- -----------
667582751824 永泰 1050 3 1
1050 福州 1003 2 2
1003 福建 0 1 3
在 Oracle 语法中,层次查询的语法与 Mssql 中不一样,以前在用到的时候,一直难以理解是怎么个关联关系的,直到在一个博客中看到一种说法:prior 就是"找"的意思,prior id 就是找叶子节点,自顶而下查询;prior parent_id 就是找父节点,即自底向上查询。这样解释起来就非常有意思而且便于记忆,是个非常棒的点。以下是 Oracle / DM 对应的SQL。
select * from test start with id=1003 connect by prior id= main_id;
select a.*,level from test a start with id = 667582735385 connect by prior main_id = id;
SQL-递归查询在Ora与Mssql的更多相关文章
- SQL递归查询实现跟帖盖楼效果
网易新闻的盖楼乐趣多,某一天也想实现诸如网易新闻跟帖盖楼的功能,无奈技术不佳(基础不牢),网上搜索了资料才发现SQL查询方法有一种叫递归查询,整理如下: 一.查询出 id = 1 的所有子结点 wit ...
- 【转】sql递归查询问题
原文链接地址http://www.cnblogs.com/sweting/archive/2009/06/08/1498483.html 在工作中遇到一个问题,是需要sql递归查询的.不懂,于是到cs ...
- SQL递归查询(with as)
SQL递归查询(with cte as) with cte as( select Id,Pid,DeptName,0 as lvl from Department where Id = 2 ...
- 关于SQL递归查询在不同数据库中的实现方法
比如表结构数据如下: Table:Tree ID Name ParentId 1 一级 0 2 二级 1 3 三级 2 4 四级 3 SQL SERVER 2005查询方法: //上查 with ...
- SQL递归查询知多少
最近工作中遇到了一个问题,需要根据保存的流程数据,构建流程图.数据库中保持的流程数据是树形结构的,表结构及数据如下图: 仔细观察表结构,会发现其树形结构的特点: FFIRSTNODE:标记是否为根节点 ...
- sql递归查询语句
sql Bom 递归查询: with t as(select * from Department where id=6union allselect a.* from Department a,t w ...
- PLSQL Developer概念学习系列之登录连接Oracle时出现(没有登录) -PL / SQL Developer:ORA - 12541: TNS :无建听程序的错误解决办法(图文详解)
不多说,直接上干货! 前期博客 PLSQL Developer概念学习系列之如何正确登录连接上Oracle(图文详解) 如用scott.scott_password进行登录,orcl是全局数据库 ...
- SQL监控:mysql及mssql数据库SQL执行过程监控审计
转载 Seay_法师 最近生活有很大的一个变动,所以博客也搁置了很长一段时间没写,好像写博客已经成了习惯,搁置一段时间就有那么点危机感,心里总觉得不自在.所以从今天起还是要继续拾起墨笔(键盘),继续好 ...
- SQL递归查询实现组织机构树
系统用到的组织机构树,要实现对当前节点以及其子节点的查询,数据库SQL要用到递归查询,这也是我第一次接触SQL的递归查询. 先说一下什么是递归查询,简单说来是将一个树状结构存储在一张表里,比如一个表中 ...
随机推荐
- 人工智能--AI篇
AI背景 在当今互联网信息高速发展的大背景下,人工智能(AI)已经开始走进了千家万户,逐渐和我们的生活接轨,那具体什么是AI呢? 什么是人工智能(AI)? 人工智能:简单理解就是由人制造出来的,有一定 ...
- php抓取图片进行内容提取解析,文字性pdf进行内容文字提取解析
2018年7月7日18:52:17 php是用纯算法,自己是提取图片内容不是不行,可以但是优化起来很麻烦还得设计学习库,去矫正数据的正确率 对于大多数项目来说,如果不是做ocr服务,就不必要做需求工具 ...
- Python通过简单的文件读写,来实现注册登录
# -*- coding:utf-8 -*- '''''' username = input('请输入您的姓名:') password = input('请输入密码:') with open('get ...
- 2019年春季学期第二周作业 基础作业 请在第一周作业的基础上,继续完成:找出给定的文件中数组的最大值及其对应的最小下标(下标从0开始)。并将最大值和对应的最小下标数值写入文件。 输入: 请建立以自己英文名字命名的txt文件,并输入数组元素数值,元素值之间用逗号分隔。 输出 在不删除原有文件内容的情况下,将最大值和对应的最小下标数值写入文件
~~~ include<stdio.h> include<stdlib.h> int main() { FILE*fp; int i=0,max=0,j=0,maxb=0; i ...
- spring注解简单记录
@Autowired 自动匹配,按类型 @qualifiter("beanname") 当有多个bean匹配时,可指定bean名称 @Resource byname优先匹配,然后b ...
- CSIS 1119B/C Introduction to Data Structures and Algorithms
CSIS 1119B/C Introduction to Data Structures and Algorithms Programming Assignment TwoDue Date: 18 A ...
- iOS的签名机制
1.从keychain里“从这证书颁发机构请求证书”,这样就在本地生成了一对公私钥,保存的CertificateSigningRequest就是公钥,私钥保存在本地电脑里. 2.苹果自己有一对固定的公 ...
- HDD ,SSD和PCIE SSD性能测试
PCIE SSD * MB/s = 1,000,000 bytes/s [SATA/600 = 600,000,000 bytes/s] * KB = 1000 bytes, KiB = 10 ...
- MySQL使用root权限创建用户并授权
MySql篇 1.下载并安装Mysql (1)下载地址 MySQL-8.0下载地址 (2)Mysql配置 1.home目录下命令行执行:vi .bash_profile来配置MySql绝对路径 ...
- PowerBI/Excel - PowerQuery数据转换系列 - 如何将多行的值串联到一行 - 行列转换
Power Query 是做数据转换.数据清洗的利器,不管是在Excel还是PowerBI,如何玩好Power Query是成功建模的必不可少的一步. 今天要get到的一个新技巧:行列转换 如何将多行 ...