时间:2021-07-01 10:21:17 帮助过:14人阅读
这里才发现,在 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
标签:部分 工作 记忆 acl strong 类型 har tab 移植