前言

前几天朋友问我,关于SQLServer数据库中对树形结构的表数据统计问题,需求大致如下:

分类表(递归数据),A的子分类是B,B的子分类是C……分类关系不间断,A为第一层,B为第二层,C为第三层……需要统计“每个分类所在的层数”、“子分类的总数”和“子分类的层数”。

解决思路:

创建示例表结构,代码如下:

  1. -- 分类示例表
  2. create table temp_class
  3. (
  4. classId int primary key identity(1,1), -- 分类ID,主键,递增
  5. className nvarchar(50), -- 分类名称
  6. pcId int default 0, -- 父级分类ID0表示最顶层
  7. uLevel int, -- 层数
  8. nextUCount int, -- 子分类的总数
  9. nextLevelCount int -- 子分类的层数
  10. );
  11. -- 层数字段添加索引
  12. -- create index ind_tempClass_uLevel on temp_class(uLevel);
  13.  
  14. -- 添加测试数据。。。。。。

步骤一:每个分类所在的层数

根据树形数据结构的规律,在统计层数时,需要从最顶层向下累计,代码如下:

  1. -- 1、更新层数(pcId=0 表示第一层)
  2. -- 更新最顶层
  3. declare @i int=1; -- 第一层
  4. update temp_class set uLevel=@i where pcId=0;
  5. while(1=1)
  6. begin
  7. if(not exists(select top 1 1 from temp_class a where exists(select top 1 1 from temp_class b where b.uLevel=@i and b.classId=a.pcId)))
  8. break; -- 无下层数据,跳出循环
  9. -- 更新下一层
  10. update a set a.uLevel=@i+1 from temp_class a where exists(select top 1 1 from temp_class b where b.uLevel=@i and b.classId=a.pcId);
  11. -- 增加一层
  12. set @i=@i+1;
  13. end;

步骤二:子分类的总数

在第一步中,已经统计出了分类的层数,在统计每个分类的子分类个数时,就从最底层统计起来,本层子分类的个数就等于下一层中子分类的个数之和加上下一层的分类数量,代码如下:

  1. -- 2、更新子分类的总数
  2. -- 获取最低层分类(最大的层数)
  3. declare @maxLevel int=1;
  4. select @maxLevel=MAX(uLevel) from temp_class;
  5. -- 更新最底层的子分类总数为 0
  6. update temp_class set nextUCount=0 where uLevel=@maxLevel;
  7. -- 从最底层向上累计子分类总数
  8. while(1=1)
  9. begin
  10. set @maxLevel=@maxLevel-1;
  11. if(@maxLevel<=0) -- 层数走完,退出
  12. break;
  13. -- 更新上一层的子分类的总数
  14. update a set a.nextUCount=isnull(b.nextUCount,0) from temp_class a
  15. left join
  16. -- 父级(本层)分类的个数=下一层中子分类的个数之和+下一层的分类数量
  17. (select pcId,SUM(nextUCount)+COUNT(classId) nextUCount from temp_class where uLevel=@maxLevel+1 group by pcId) b
  18. on a.classId=b.pcId
  19. where a.uLevel=@maxLevel;
  20. end;

步骤三:子分类的层数

在第一步中,已经统计出了分类的层数,在统计每个分类的子分类层数时,就从最底层统计起来,本层子分类的层数就等于下一层中子分类的层数最大值加上一层,代码如下:

  1. -- 3、更新子分类的层数
  2. -- 获取最低层子分类(最大的层数)
  3. declare @maxLevel int=1;
  4. select @maxLevel=MAX(uLevel) from temp_class;
  5. -- 更新最底层的子分类层数为 0
  6. update temp_class set nextLevelCount=0 where uLevel=@maxLevel;
  7. -- 从最底层向上累计层数
  8. while(1=1)
  9. begin
  10. set @maxLevel=@maxLevel-1;
  11. if(@maxLevel<=0) -- 层数走完,退出
  12. break;
  13. -- 更新上一层的子分类层数
  14. update a set a.nextLevelCount=ISNULL(b.nextLevelCount,0) from temp_class a
  15. left join
  16. -- 父级(本层)分类的层数=下一层中子分类的最大层数+1(当前子分类为 1 层)
  17. (select pcId,(MAX(nextLevelCount)+1) as nextLevelCount from temp_class where uLevel=@maxLevel+1 group by pcId) b
  18. on a.classId=b.pcId
  19. where a.uLevel=@maxLevel;
  20. end;

查询结果:

后言

该随笔仅当个人笔记所用,路过的大神如有好的建议,还请赐教,菜鸟再此感激不尽!

SQLServer树形数据结构的数据进行数据统计的更多相关文章

  1. SQLSERVER是怎麽通过索引和统计信息来找到目标数据的(第三篇)

    SQLSERVER是怎麽通过索引和统计信息来找到目标数据的(第三篇) 最近真的没有什么精力写文章,天天加班,为了完成这个系列,硬着头皮上了 再看这篇文章之前请大家先看我之前写的第一篇和第二篇 第一篇: ...

  2. 不制作证书是否能加密SQLSERVER与客户端之间传输的数据?

    不制作证书是否能加密SQLSERVER与客户端之间传输的数据? 在做实验之前请先下载network monitor抓包工具 微软官网下载:http://www.microsoft.com/en-us/ ...

  3. SharePoint2010沙盒解决方案基础开发——关于TreeView树形控件读取列表数据(树形导航)的webpart开发及问题

    转:http://blog.csdn.net/miragesky2049/article/details/7204882 SharePoint2010沙盒解决方案基础开发--关于TreeView树形控 ...

  4. SQLSERVER手动增长日志文件和数据文件

    原文:SQLSERVER手动增长日志文件和数据文件 SQLSERVER手动增长日志文件和数据文件 手动增长日志文件,实际上就是修改日志文件的大小  size 的单位是MB 下面设置日志文件大小是204 ...

  5. 使用SQLServer 2008的CDC功能实现数据变更捕获

    原文:使用SQLServer 2008的CDC功能实现数据变更捕获 最近由于工作需要,研究了一下2008 CDC功能,觉得还不错,下面整理了一下研究过程,虽然比较粗略,但是基本上能用了,如果有补充请大 ...

  6. SQLServer通过链接服务器远程删除数据性能问题解决

    原文:SQLServer通过链接服务器远程删除数据性能问题解决 在上一遍文章中介绍了SQLServer通过链接服务器访问Oracle性能问题的解决方法,本文介绍链接服务器下远程删除SQLServer数 ...

  7. SQLServer中处理亿万级别的数据

    在SQLServer中处理亿万级别的数据(历史数据),可以按以下方面进行: 去掉表的所有索引 用SqlBulkCopy进行插入 分表或者分区,减少每个表的数据总量 在某个表完全写完之后再建立索引 正确 ...

  8. SQLServer转MYSQL的方法(连数据)[传]

    转自 https://blog.csdn.net/AlbenXie/article/details/77449720 SQLServer转MYSQL的方法(连数据) 本次转换需要依赖使用工具Navic ...

  9. 用servlet来提取数据,并作统计,然后用jfreechart画图

    指定时间范围的数据提取,并做统计: 用servlet来提取数据,并作统计,然后用jfreechart画图. 使用的话,需要在web.xml里面配置相应的servlet,并且在index.jsp页面做引 ...

随机推荐

  1. 手机自动化测试:appium源码分析之bootstrap四

    手机自动化测试:appium源码分析之bootstrap四   Orientation是调整屏幕方向的操作 package io.appium.android.bootstrap.handler; i ...

  2. 《完全用Linux工作》

    <完全用Linux工作>作者:王垠 完全用 GNU/Linux 工作 理解 GNU/Linux 更多精彩请直接访问SkySeraph个人站点:www.skyseraph.com 注:本文是 ...

  3. Redis基础学习(四)—Redis的持久化

    一.概述      Redis的强大性能很大程度上都是因为数据时存在内存中的,然而当Redis重启时,所有存储在内存中的数据将会丢失,所以我们要将内存中的数据持久化. Redis支持两种数据持久化的方 ...

  4. Redis基础学习(三)—Key操作

    一.key的相关操作 1.删除 del key1 key2 ... Keyn 作用: 删除1个或多个键. 返回值: 不存在的key忽略掉,返回真正删除的key的数量.   2.重命名 rename k ...

  5. mac上使用使用rz,sz命令

    mac上使用rz,sz命令,mac上的终端不支持rz 和sz,所以安装iterm并配置使用rz和cz 1.首先需要下载安装iterm2,下载地址:下载后安装 http://www.iterm2.cn/ ...

  6. Apache2.4.23+PHP5.6.30+MySQL5.7.18安装教程

    最近在工作中常常接触到PHP,自己也写过一些简单的PHP页面.我们知道PHP是在服务器端运行的脚本语言,因此我们需要配置服务器环境.之前为了省事直接使用的是wamp集成环境,但是突然某一天领导要求我们 ...

  7. cookie和session的区别异同

    1.用于保存页面信息:如自动登录,记住用户名 2.对于同一个网站只有一套cookie,它是以域名为单位的,一个域名就是一套,数量大小有限4k-10k,同时会具有过期时间 3.JS中通过document ...

  8. CF #349 div1 B. World Tour

    题目链接:http://codeforces.com/problemset/problem/666/B 大意是给一张有向图,选取四个点,使得走这四个点,任意两个点之间走最短路,总距离最长. 3000个 ...

  9. Linux 练习(1)

    1) 新建用户natasha,uid为1000,gid为555,备注信息为"master" useradd -u 1000 -g 555 -c 'master' natasha2) ...

  10. summerDao-比mybatis更强大无需映射配置的dao工具

    summerDao是summer框架中的一个数据库操作工具,项目地址:http://git.oschina.net/xiwa/summer. 怎么比mybatis更强大,怎么比beetlsql更简单, ...