在数据查询中,从2008开始SQL Server提供了一个新的数据类型hierarchyid,专门用来操作层次型数据结构。

hierarchyid 类型对层次结构树中有关单个节点的信息进行逻辑编码的方法是:对从树的根目录到该节点的路径进行编码。

这种路径在逻辑上表示为一个在根之后被访问的所有子级的节点标签序列。 表示形式以一条斜杠开头,只访问根的路径由单条斜杠表示。 对于根以下的各级,各标签编码为由点分隔的整数序列。 子级之间的比较就是按字典顺序比较由点分隔的整数序列。 每个级别后面紧跟着一个斜杠。 因此斜杠将父级与其子级分隔开。 例如,以下是长度分别为 1 级、2 级、2 级、3 级和 3 级的有效 hierarchyid 路径:

• /

• /1/

• /0.3.-7/

• /1/3/

• /0.1/0.2/

在没有hierarchyid的日子里,我们通过CTE的方式来查询父以及全部的下级,但是,数据量多的情况下,CTE的方式将会变的很慢,后来,我们通过构造PATH的方式来加快速度。那么,有了hierarchyid类型后,自然得使用hierarchyid了。

现在,通过一个实际的例子来看看hierarchyid的威力。

一:CTE方式WITH CTEGetChild AS

(

SELECT * FROM EL_Organization.Organization WHERE ID='ecc43c7159924dca91e2916368f923f4' --and [State]=0 and AuditState=2

UNION ALL

(

SELECT A.* FROM EL_Organization.Organization AS A

INNER JOIN CTEGetChild AS B ON a.PARENTID=B.ID --and A.[State]=0 and A.AuditState=2

)

)

查询出来4489行,需要25S。

看来CTE方式已经到了不能容忍的地步,那么,现在,我们就用它来进行优化。

二:hierarchyid

首先,我们得新建该字段,然后为其赋值,create function f_cidname(@id varchar(50)) returns varchar(max) as

begin

declare @pids nvarchar(max);

declare @pNames nvarchar(max);

set @pids='';

set @pNames='';

with cte as

( select id,parentid,name from EL_Organization.Organization where id =@id--'00037fdf184e48d084b87c3499e3c0e5'

union all

select b.id,b.parentid,b.name from cte A ,EL_Organization.Organization B where a.parentid = b.id

)

select @pids=convert(varchar(32),Convert(int, Convert(varbinary(max), id))) + '/'+ @pids from cte

return [email protected]

end

go

接着,我们需要Update全表:UPDATE EL_Organization.Organization SET PIDS=dbo.f_cidname(id)

注意,id是guid的32位字符串,而hierarchyid字段不支持那么大的Path内路径,于是我们将GUID转为了整型:convert(varchar(32),Convert(int, Convert(varbinary(max), id)))

2.1 TIPException message: DataReader.GetFieldType(4) returned null. Exception data: System.Collections.ListDictionaryInternal

注意,极有可能我们把字段更新上去后,我们的程序却出错了,如上。这个时候,我们需要把C:\Program Files\Microsoft SQL Server\100\SDK\Assemblies\Microsoft.SqlServer.Types.dll

这个DLL打包到我们的应用程序中去。原因不解释了。

看看效果吧,修改过后的代码为:DECLARE @tmpIds hierarchyid

SELECT @tmpIds=Pids FROM EL_Organization.Organization WHERE ID='ecc43c7159924dca91e2916368f923f4';

WITH CTEGetChild AS (

SELECT * FROM EL_Organization.Organization WHERE ID='ecc43c7159924dca91e2916368f923f4'

UNION ALL(

SELECT * FROM EL_Organization.Organization WHERE Pids.IsDescendantOf(@tmpIds)=1

)

)

SELECT * FROM CTEGetChild

现在,我们的时间到了1S内。

2.2 一切为了不动应用层代码

现在,既然,增加了一个字段,我们就要维护这个字段,如:本条记录在应用程序中被移动到了别的父级下,就需要更新这个字段。为了不动上层代码,唯一能做的就是创建触发器,即:原有的ParentId变动的时候,就需要更新这个PIds字段,于是,我们创建触发器如下:create trigger UpdateOrgPIds

on EL_Organization.Organization

after update

as

if update ([ParentId])

begin

declare @tmpId varchar(36)

select @tmpId=id from inserted

update EL_Organization.Organization set pids=dbo.f_cidname(@tmpId)

end

go

-- drop trigger EL_Organization.UpdateOrgPIds

mysql树状查询优化_解析SQL中树形分层数据的查询优化相关推荐

  1. php和mysql处理树状_分级_无限分类_分层数据的方法_PHP和MySQL处理树状、分级、无限分类、分层数据的方法...

    文章标题中的多个词语表达的其实是一个意思,就是递归分类数据,分级数据非常类似数据结构中的树状结构,即每个节点有自己的孩子节点,孩子结点本身也是父亲节点.这是一个递归.分层形式.可以称之为树形层级数据. ...

  2. PHP和MySQL处理树状、分级、无限分类、分层数据的方法

    文章标题中的多个词语表达的其实是一个意思,就是递归分类数据,分级数据非常类似数据结构中的树状结构,即每个节点有自己的孩子节点,孩子结点本身也是父亲节点.这是一个递归.分层形式.可以称之为树形层级数据. ...

  3. mongodb存储数据_在MongoDB中存储分层数据

    mongodb存储数据 继续使用MongoDB进行 NoSQL之旅,我想谈一谈一个经常出现的特定用例:存储分层文档关系. MongoDB是很棒的文档数据存储,但是如果文档具有父子关系,该怎么办? 我们 ...

  4. mysql树状数据结构_树状结构的数据表如何设计?

    使用Modified Preorder Tree简直是必须的.网上可以搜一下modified preorder tree travesal找到相关资料.参考 http://www.sitepoint. ...

  5. 下拉菜单实现树状结构_树形图:复杂层次结构的数据可视化

    树形图:复杂层次结构的数据可视化 作者:Page Laubheimer[1] 树形图是一种复杂的,基于区域的数据可视化,用于复杂层次结构的数据,可能难以精确解释.在许多情况下,最好使用更简单的可视化效 ...

  6. mysql单价乘以数量_数据库字段中存储的数据数量乘以不同单价的和的算法示例...

    数据库字段中存储的数据数量乘以不同单价的和的算法,适用于记账本程序的计件数据记录,和商品记录等场景. 代码示例如下: //模拟数据库结果集 $arr = array( array( "id& ...

  7. mysql 动态sql 解析json数据_在SQL 中生成JSON数据

    这段时间接手一个数据操作记录的功能,刚拿到手上的时候打算用EF做,后来经过仔细考虑最后还是觉定放弃,最后思考再三决定: 1.以模块为单位分表.列固定(其实可以所有的操作记录都放到同一个表,但是考虑到数 ...

  8. mysql版本链图解_图解 SQL 中各种连接 JOIN

    先用文字来捋一下思路,数据库操作中无非就是「增删查改」,其中「 查」用得最多且最复杂,变化多端.查询的时候,我们可以只是单表查询,也可以是多表连接查询,单表查询中的学问也很大,但限于篇幅,本次主要分享 ...

  9. mysql时间区间效率_对于sql中使用to_timestamp判断时间区间和不使用的效率对比及结论...

    关于日期函数TO_TIMESTAMP 拓展: date类型是Oracle常用的日期型变量,时间间隔是秒.两个日期型相减得到是两个时间的间隔,注意单位是"天". timestamp是 ...

最新文章

  1. Javascript阻止表单提交
  2. VS高版本编写C程序的C4996错误
  3. 熬夜都要看完的 Spring 干货!
  4. Mybatis中(#{ })模糊查询like(使用oracle的concat函数嵌套拼接SQL)
  5. python在命令端口运行脚本_扫描端口占用情况的python脚本
  6. Mbatis是什么?怎么运行?
  7. linux stat文件,Linux stat命令:显示文件或文件系统的详细信息
  8. Myeclipse学习总结(1)——Myeclipse优化配置
  9. 为什么你看了很多书,却依然没有洞见?
  10. CSS基础选择器之类选择器(CSS、HTML)
  11. 对抗搜索之【最大最小搜索】【Alpha-Beta剪枝搜索】
  12. 共建信创生态,助力组织国产化进程
  13. VSCode 搭建 STM32 开发环境
  14. Draco压缩算法使用
  15. B/S结构和C/S结构详细介绍
  16. ps磨皮插件专用智能磨皮插件 AI算法美颜 提高P图效率
  17. 如何在printf中输出,特殊字符(如:%、\、““)或表示八进制012、十六进制0xc
  18. android内存分析命令
  19. Echarts-gl geo3D设置regions区域高度
  20. 线性代数第四章 向量组的线性相关性

热门文章

  1. VirtualBox中使用双网卡实现CentOS既能上网(校园网)也能使用SSHclient
  2. windows Ctrl + Alt + 方向键 取消屏幕反转
  3. linux网络流量实时监控工具之iptraf 【个人比较喜欢用的流量监控软件】
  4. JMX 简介 和 实例
  5. 写帮助大家学习的小框架
  6. (转)uml 静态视图关系和关联
  7. 通用客户端表单验证函数修正版(zz)
  8. 浅谈Flutter的状态State
  9. Springboot2.x使用redis作为缓存
  10. mobile web页面调试方法