SqlServr性能优化性能之层次结构(十五)
1.添加根节点: hierarchyid GetRoot()方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | --创建数据库 create table Employeeh(EmployeeID int , Name varchar (500),ManagerID int ,EmplyeeNode hierarchyID) --添加根节点的记录 insert Employeeh values (1, 'CEO' , null ,hierarchyid::GetRoot()) --添加两个平级的子节点 --1.定义父节点 declare @rootmanager hierarchyid --对变量进行赋值 set @rootmanager=( select EmplyeeNode from Employeeh where EmployeeID=1) --父节点作为子节点进行插入 insert Employeeh values (2, 'Manager1' ,1,@rootmanager.GetDescendant( null , null )) --插入第二条数据 declare @manager1 hierarchyid set @manager1=( select EmplyeeNode from Employeeh where EmployeeID=2) insert Employeeh values (3, 'Manager2' ,1,@rootmanager.GetDescendant(@manager1, null )) --访问表的数据 select EmployeeID, Name ,ManagerID,EmplyeeNode.ToString() from Employeeh |
结果:
2.添加子节点:父节点GetDescendant()方法
在子节点中在添加子节点:
1 2 3 4 5 6 7 8 | --在Manager1 中添加子节点 declare @manager1 hierarchyid set @manager1=( select EmplyeeNode from Employeeh where EmployeeID=3) insert Employeeh values (4, 'SubManager1' ,2,@manager1.GetDescendant( null , null )) declare @manager2 hierarchyid set @manager2=( select EmplyeeNode from Employeeh where EmployeeID=3) insert Employeeh values (5, 'SubManager2' ,3,@manager2.GetDescendant( null , null ))<br><br> --查询<br>select EmployeeID,Name,ManagerID,EmplyeeNode.ToString() from Employeeh<br> |
1 2 3 | --访问节点所在的层次结构 select EmployeeID, Name ,ManagerID,EmplyeeNode.ToString(),EmplyeeNode.GetLevel() from Employeeh |
3.获取当前级别:当前节点GetLevel()方法
4.获取当前节点下所有子节点,判断条件:where 列名 IsDescendantOf(当前节点)=1 or 0
1 2 3 4 5 6 7 | --查看当前节点下的子节点 --1.申明当前的节点 declare @ current hierarchyid set @ current =( select EmplyeeNode from Employeeh where Name = 'Manager2' ) select EmployeeID, Name ,ManagerID,EmplyeeNode.ToString(),EmplyeeNode.GetLevel() from Employeeh --判断当前节点的子节点为真 where EmplyeeNode.IsDescendantOf(@ current )=1 |
5.获取当前节点的父节点:判断条件:where 列名 当前节点 GetAncestor(级别)
1 2 3 4 5 | --查看当前节点所在的父节点 declare @ current hierarchyid set @ current =( select EmplyeeNode from Employeeh where Name = 'SubManager2' ) select EmployeeID, Name ,ManagerID,EmplyeeNode.ToString(),EmplyeeNode.GetLevel() from Employeeh where EmplyeeNode=@ current .GetAncestor(1) |
6.移动节点到新的父节点:Set 列名=当前节点 GetReparentedValue(@OldParent,@NewParent) where
7.索引:深度优化(查询所有的后代)、宽度优先(查询直接后代)
将旧表数据导入层次结构数据新表
新建旧表插入数据:
1 2 3 4 5 6 7 8 | create table EmployeeOld(employeeid int ,managerid int , name varchar (500)) insert EmployeeOld values (1, null , 'ceo' ) insert EmployeeOld values (2,1, 'manager1' ) insert EmployeeOld values (3,1, 'manager2' ) insert EmployeeOld values (4,2, 'sub1' ) insert EmployeeOld values (5,2, 'sub2' ) insert EmployeeOld values (6,3, 'sub3' ) insert EmployeeOld values (7,3, 'sub4' ) |
把旧表的数据导入到新表中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | --创建新表(有层次结构的表) create table EmployeeNew(employeeid int ,managerid int , name varchar (500),node hierarchyid) --查看以前的表结构 select EmployeeID, Name ,ManagerID,EmplyeeNode.ToString() from Employeeh --思路:1.获取子节点在父节点下所对应的的行号 --2.将父节点的hierarchyid 给链接到行号的前面 --1.通用表表达式 获取旧表的数据 并且存储在父节点下的行号 --2.第二个通用表达式使用第一个通用表达式的值,同时连接父节点 hierarchyid的值 ; with eh(employeeid,managerid, name ,position) as ( select employeeid,managerid, name ,ROW_NUMBER() over(partition by managerid order by employeeid) from EmployeeOld ), employeenewtemp(employeeid,managerid, name ,node) as ( select employeeid,managerid, name ,hierarchyid::GetRoot() from eh where managerid is null union all select eh.employeeid,eh.managerid,eh. name , CAST (employeenewtemp.node.ToString()+ CAST (eh.position as varchar (500)) + '/' as hierarchyid) from eh inner join employeenewtemp on eh.managerid=employeenewtemp.employeeid ) --插入到新表中 insert into EmployeeNew select employeeid,managerid, name ,node.ToString() from employeenewtemp |
查看数据:
1 2 | select * from EmployeeOld select employeeid,managerid, name ,node.ToString() from EmployeeNew |
C#中控制台调用。
一:建立连接返回数据
引入这个命名空间
1 | using Microsoft.SqlServer.Types; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public DataTable getdata() { SqlConnection conn = new SqlConnection( "data source=localhost;initial catalog=HRDB1;user id=sa;password=sunliyuan123456" ); //打开连接 conn.Open(); //执行Sql语句 SqlDataAdapter da = new SqlDataAdapter( "select * from EmployeeNew" , conn); //实例化DataSet DataSet ds = new DataSet(); //进行填充 da.Fill(ds, "EmployeeNew" ); //释放资源 ds.Dispose(); conn.Close(); //返回第一个表 return ds.Tables[0]; } |
二:生成树节点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | /// <summary> /// 生成树的节点 /// </summary> /// <param name="oParent">树节点</param> /// <param name="oTable">得到的表</param> private void LoadTreeNode(TreeNode oParent,DataTable oTable) { //清空所有的节点 oParent.Nodes.Clear(); //取得父节点的数据 放入DataRow DataRow oRow=(DataRow)oParent.Tag; //获取node的值并进行转换 SqlHierarchyId iID =(SqlHierarchyId)oRow[ "node" ]; //的到第一节父节点 出入的值是父节点的id 说明传进来的值就是子节点 var query = from employee in oTable.AsEnumerable() where employee.Field<SqlHierarchyId>( "node" ).GetAncestor(1) .Equals(iID) select employee; //把数据放入到DataView 中 DataView oDV = query.AsDataView(); foreach (DataRowView oR in oDV) { //得到一节子节点 TreeNode oNode = new TreeNode(oR[ "name" ].ToString()); oNode.Tag = oR.Row; LoadTreeNode(oNode,oTable); //附加到父节点 oParent.Nodes.Add(oNode); } } |
三:生成树视图并得到根节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | /// <summary> /// 生成树视图并得到根节点 /// </summary> /// <param name="oTV"></param> /// <param name="oTable"></param> /// <param name="key"></param> /// <param name="text"></param> public void LoadTreeView(TreeView oTV,DataTable oTable, string key, string text) { oTV.Nodes.Clear(); SqlHierarchyId iID = new SqlHierarchyId(); TreeNode roonode; //查询根节点 var query = from employee in oTable.AsEnumerable() where employee.Field<SqlHierarchyId>(key).GetAncestor(1) .Equals(iID) select employee; DataView oDV = query.AsDataView(); //找到根节点 if (oDV.Count ==1) { roonode = new TreeNode(oDV[0][text].ToString()); roonode.Tag = oDV[0].Row; LoadTreeNode(roonode, oTable); oTV.Nodes.Add(roonode); } } |
对数据进行绑定:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | private clsData oData = new clsData(); private DataTable dtData; private void btnGetData_Click( object sender, EventArgs e) { dtData = oData.getdata(); dgData.DataSource = dtData; } private void btnClose_Click( object sender, EventArgs e) { this .Close(); } private void doTV_Click( object sender, EventArgs e) { oData.LoadTreeView(tvData, dtData, "node" , "name" ); } |
效果:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决