今天在工作中,有同事“请教”从 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的更多相关文章

  1. SQL递归查询实现跟帖盖楼效果

    网易新闻的盖楼乐趣多,某一天也想实现诸如网易新闻跟帖盖楼的功能,无奈技术不佳(基础不牢),网上搜索了资料才发现SQL查询方法有一种叫递归查询,整理如下: 一.查询出 id = 1 的所有子结点 wit ...

  2. 【转】sql递归查询问题

    原文链接地址http://www.cnblogs.com/sweting/archive/2009/06/08/1498483.html 在工作中遇到一个问题,是需要sql递归查询的.不懂,于是到cs ...

  3. SQL递归查询(with as)

    SQL递归查询(with cte as) with cte as(    select Id,Pid,DeptName,0 as lvl from Department    where Id = 2 ...

  4. 关于SQL递归查询在不同数据库中的实现方法

    比如表结构数据如下: Table:Tree ID Name ParentId 1 一级  0 2  二级 1 3  三级 2 4 四级 3 SQL SERVER 2005查询方法: //上查 with ...

  5. SQL递归查询知多少

    最近工作中遇到了一个问题,需要根据保存的流程数据,构建流程图.数据库中保持的流程数据是树形结构的,表结构及数据如下图: 仔细观察表结构,会发现其树形结构的特点: FFIRSTNODE:标记是否为根节点 ...

  6. sql递归查询语句

    sql Bom 递归查询: with t as(select * from Department where id=6union allselect a.* from Department a,t w ...

  7. PLSQL Developer概念学习系列之登录连接Oracle时出现(没有登录) -PL / SQL Developer:ORA - 12541: TNS :无建听程序的错误解决办法(图文详解)

    不多说,直接上干货! 前期博客 PLSQL Developer概念学习系列之如何正确登录连接上Oracle(图文详解)   如用scott.scott_password进行登录,orcl是全局数据库 ...

  8. SQL监控:mysql及mssql数据库SQL执行过程监控审计

    转载 Seay_法师 最近生活有很大的一个变动,所以博客也搁置了很长一段时间没写,好像写博客已经成了习惯,搁置一段时间就有那么点危机感,心里总觉得不自在.所以从今天起还是要继续拾起墨笔(键盘),继续好 ...

  9. SQL递归查询实现组织机构树

    系统用到的组织机构树,要实现对当前节点以及其子节点的查询,数据库SQL要用到递归查询,这也是我第一次接触SQL的递归查询. 先说一下什么是递归查询,简单说来是将一个树状结构存储在一张表里,比如一个表中 ...

随机推荐

  1. hadoop三个配置文件的参数含义说明

    1       获取默认配置 配置hadoop,主要是配置core-site.xml,hdfs-site.xml,mapred-site.xml三个配置文件,默认下来,这些配置文件都是空的,所以很难知 ...

  2. Gym 101908C - Pizza Cutter - [树状数组]

    题目链接:https://codeforces.com/gym/101908/problem/C 题意: 一块正方形披萨,有 $H$ 刀是横切的,$V$ 刀是竖切的,不存在大于等于三条直线交于一点.求 ...

  3. 2018-2019-2 《网络对抗技术》Exp0 Kali安装 Week1 20165225

    2018-2019-2 <网络对抗技术>Exp0 Kali安装 Week1 20165225 - 上Kali官网选择Kali Linux 64 bit的torrent,用迅雷解压即可 安装 ...

  4. CentOS 7 - 最小化安装后,解决无法使用yum命令问题!!

    刚刚最小化方式安装了CentOS 7 后,说实话,真不习惯也不喜欢纯shell方式工作,使用root账号登入后,马上想安装GNOME,但是发现yum不能正常工作!!! 一,输入安装X Window命令 ...

  5. Zookeeper基本信息

    Zookeeper特点: 1.中间件,提供协调服务 2.作用于分布式系统,可以为大数据服务 3.支持java,提供java和c语言的客户端的api 分布式系统: 1.很多台计算机组成一个整体,一个整体 ...

  6. LigerUi之ligerMenu 右键菜单

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  7. des加密算法java&c#

    项目中用到的数据加密方式是ECB模式的DES加密得到的十六进制字符串.技术支持让写一个.net版的加密算法.这里做一下记录. java版: 16进制使用的是bouncycastle. import c ...

  8. 判断是否引入jQuery,没有则引入

    <script type="text/javascript"> window.jQuery || document .write("<script sr ...

  9. python数据类型之集合类型

    一.集合的作用 知识点回顾:可变类型是不可hash类型,不可变类型是可hash类型 作用:去重,关系运算 定义:可以包含多个元素,用逗号分割,集合的元素遵循三个原则: 1.每个元素必须是不可变类型(可 ...

  10. qt 画多边形(实现鼠标拖动节点)

    ---恢复内容开始--- 2018-01-06 这个小例子实现了移动鼠标,鼠标的坐标信息跟随鼠标移动,多边形的实现,鼠标点击可以拖动多边形点的位置,(其中有个问题?我在QMainWindow下,用mo ...