zoukankan      html  css  js  c++  java
  • SQL Server 实现递归获取层级数据

    经常会出现一个业务场景,当前已知ID,怎么获取他的子节点数据呢?怎么获取父节点的数据呢?下面用代码展示一个最简单的例子:
    /*创建一张员工表*/
    CREATE TABLE [dbo].[Employee](
        [ID] [uniqueidentifier] NOT NULL,--用户ID
        [ParentGUID] [uniqueidentifier] NOT NULL,--上级ID
        [ECode] [nvarchar](50) NOT NULL,--员工编号
        [EName] [nvarchar](200) NOT NULL--员工名称
     CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED 
    (
        [ID] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    /*插入几条基础数据*/
    INSERT [dbo].[Employee] ([ID], [ParentGUID], [ECode], [EName]) VALUES (N'CF06903A-1D9B-4896-916E-56E4B8CB1955', N'00000000-0000-0000-0000-000000000000', N'SG001', N'董事长')
    INSERT [dbo].[Employee] ([ID], [ParentGUID], [ECode], [EName]) VALUES (N'DD994FDA-1703-4616-AF1B-165164DF710E', N'CF06903A-1D9B-4896-916E-56E4B8CB1955', N'SG0012', N'经理')
    INSERT [dbo].[Employee] ([ID], [ParentGUID], [ECode], [EName]) VALUES (N'138C93C0-387B-4582-8A56-E036056A97F2', N'DD994FDA-1703-4616-AF1B-165164DF710E', N'SG0013', N'部长')
    INSERT [dbo].[Employee] ([ID], [ParentGUID], [ECode], [EName]) VALUES (N'88F1D9F7-CC02-4449-BA0A-8717142FFB4D', N'138C93C0-387B-4582-8A56-E036056A97F2', N'SG0014', N'主管')
    INSERT [dbo].[Employee] ([ID], [ParentGUID], [ECode], [EName]) VALUES (N'166FA95A-0425-40E3-8CB9-2A4C97CA4CC6', N'88F1D9F7-CC02-4449-BA0A-8717142FFB4D', N'SG00141', N'邵工')
    INSERT [dbo].[Employee] ([ID], [ParentGUID], [ECode], [EName]) VALUES (N'6E94AA52-700A-4415-BB8A-34345605E13D', N'88F1D9F7-CC02-4449-BA0A-8717142FFB4D', N'SG00142', N'李工')
    INSERT [dbo].[Employee] ([ID], [ParentGUID], [ECode], [EName]) VALUES (N'C5E537D4-0994-43E2-A1AB-3F736B4E22D3', N'88F1D9F7-CC02-4449-BA0A-8717142FFB4D', N'SG00143', N'高工')
    INSERT [dbo].[Employee] ([ID], [ParentGUID], [ECode], [EName]) VALUES (N'61F79EAF-DB86-425E-A61C-4228265EEC28', N'88F1D9F7-CC02-4449-BA0A-8717142FFB4D', N'SG00144', N'卜工')
    INSERT [dbo].[Employee] ([ID], [ParentGUID], [ECode], [EName]) VALUES (N'34C26725-3726-4C45-90C0-440C91EF34B8', N'88F1D9F7-CC02-4449-BA0A-8717142FFB4D', N'SG00145', N'苏工')
    

      

    我的解决办法是使用WITH AS 语句
    WITH AS的含义
    
        WITH AS短语,也叫做子查询部分(subquery factoring),可以让你做很多事情,定义一个SQL片断,该SQL片断会
    被整个SQL语句所用到。有的时候,是为了让SQL语句的可读性更高些,也有可能是在UNION ALL的不同部分,作为提供数
    据的部分。 
        特别对于UNION ALL比较有用。因为UNION ALL的每个部分可能相同,但是如果每个部分都去执行一遍的话,则成本太高,
    所以可以使用WITH AS短语,则只要执行一遍即可。如果WITH AS短语所定义的表名被调用两次以上,则优化器会自动将
    WITH AS短语所获取的数据放入一个TEMP表里,如果只是被调用一次,则不会。而提示materialize则是强制将WITH AS
    短语里的数据放入一个全局临时表里。很多查询通过这种方法都可以提高速度。
    /*获得主管所有上司*/
    ;WITH cteTemp AS
    (
    	SELECT [ID], [ParentGUID], [ECode], [EName]
    	FROM [Employee] WHERE ID = '88F1D9F7-CC02-4449-BA0A-8717142FFB4D'/*主管ID*/
    	UNION ALL
    	SELECT A.[ID], A.[ParentGUID], A.[ECode], A.[EName]
    	FROM [Employee] A 
    	INNER JOIN cteTemp B ON A.[ID] = B.[ParentGUID]
    )
    SELECT *  FROM cteTemp
    

      

    /*获得主管所有手下*/
    ;WITH cteTemp AS
    (
    	SELECT [ID], [ParentGUID], [ECode], [EName]
    	FROM [Employee] WHERE ID = '88F1D9F7-CC02-4449-BA0A-8717142FFB4D'/*主管ID*/
    	UNION ALL
    	SELECT A.[ID], A.[ParentGUID], A.[ECode], A.[EName]
    	FROM [Employee] A 
    	INNER JOIN cteTemp B ON A.[ParentGUID] = B.[ID]
    )
    SELECT *  FROM cteTemp
    

      

     

    
    

      

      

  • 相关阅读:
    计算某天的下一天:黑盒测试之等价类划分+JUnit参数化测试
    黑盒测试之因果图法
    黑盒测试之等价类划分
    JUnit白盒测试之基本路径测试:称重3次找到假球
    Java实现称重3次找到假球
    用pymysql和Flask搭建后端,响应前端POST和GET请求,实现登录和注册功能
    【算法与数据结构】包含负数的基数排序
    【机器学习实战】第六章--支持向量机
    【机器学习实战】第四章朴素贝叶斯
    【算法与数据结构】--经典排序算法Python实现
  • 原文地址:https://www.cnblogs.com/liangsheng/p/8933854.html
Copyright © 2011-2022 走看看