树形查询扩展

数据库环境:SQL SERVER 2005

  有一层次表的数据如下图1,要实现图2的效果,即将层次结构的路径按行显示,

第一列显示的是叶子节点,后面则是分枝节点,最后是根节点。

        

  要解决的问题:

  1.递归实现树形查询

2.从根节点到叶子节点编成一组

  3.动态行转列

  好了,我们依次来解决这些问题。

  0.建表,导入基础数据

WITH x0 AS(
SELECT 1 AS id,‘1xx‘ AS name,2 AS fatherID UNION ALL
SELECT 2 AS id,‘2xx‘ AS name,3 AS fatherID UNION ALL
SELECT 3 AS id,‘3xx‘ AS name,0 AS fatherID UNION ALL
SELECT 4 AS id,‘4xx‘ AS name,3 AS fatherID UNION ALL
SELECT 0 AS id,‘0xx‘ AS name,NULL AS fatherID)

SELECT * INTO #t FROM x0

  1.递归分组

  分组的组号依据叶子节点的id而定,从叶子节点追溯到根节点,它们属于同一组。

/*递归实现层次查询*/
WITH    x0 ( id, name, fatherID, way, level )
          AS ( SELECT   id ,
                        name ,
                        fatherID ,
                        CONVERT(VARCHAR(50), CAST(id AS VARCHAR(2))) AS way ,
                        id AS level
               FROM     #t t1
               /*从叶子节点开始递归*/
               WHERE    NOT EXISTS ( SELECT NULL
                                     FROM   #t t2
                                     WHERE  t2.fatherID = t1.id )
               UNION ALL
               SELECT   t1.id ,
                        t1.name ,
                        t1.fatherID ,
                        CONVERT(VARCHAR(50), CAST(t1.id AS VARCHAR(2)) + ‘->‘
                        + t2.way) AS way ,--路径
                        t2.level--组别
               FROM     #t t1 ,
                        x0 t2
               WHERE    t1.id = t2.fatherID
             )

  层次查询的结果如图:

  2.动态行转列实现

  有了组号,我们则根据同一组号的数据转到一行上展示。这里需要注意行转列的展示顺序,

排在前面的是子节点,后面是父节点。关于动态行转列的实现,可参考我前面的博客 将部分相同的多行记录转成一行多列

SELECT  id ,
            name ,
            level ,
            ROW_NUMBER() OVER ( PARTITION BY level ORDER BY LEN(way) ) AS rn--节点的展示序号
    INTO    #t1
    FROM    x0

DECLARE @sql NVARCHAR(MAX);
SET @sql = N‘‘;
SELECT  @sql = @sql + ‘,max(case rn when ‘ + CAST(tt.rn AS VARCHAR)
        + ‘ then id end) ‘ + CASE WHEN rn = 1 THEN +‘id‘
                                  ELSE ‘faterID‘
                             END + ‘,max(case rn when ‘
        + CAST(tt.rn AS VARCHAR) + ‘ then name end) ‘
        + CASE WHEN rn = 1 THEN +‘name‘
               ELSE ‘faterName‘
          END
FROM    ( SELECT DISTINCT
                    rn
          FROM      #t1
        ) tt
ORDER BY rn;

SET @sql = N‘select level‘ + @sql + ‘ from #t1 group by level‘;
EXEC(@sql);

(本文完)

时间: 2024-10-19 20:01:21

树形查询扩展的相关文章

应用程序框架实战二十四:基础查询扩展 - 分页与排序

上一篇介绍了IQueryable的Where方法存在的问题,并扩展了一个名为Filter的过滤方法,它是Where方法的增强版.本篇将介绍查询的另一个重要主题——分页与排序. 对于任何一个信息系统,查询都需要分页,因为不可能直接返回表中的所有数据. 如果直接使用原始的Ado.Net,我们可以编写一个通用分页存储过程来进行分页查询,然后通过一个DataTable返回给业务层.不过进入Entity Framework时代,分页变得异常简单,通过Skip和Take两个方法配合就可以完成任务. 为了让分

NHibernate Linq查询 扩展增强 (第九篇)

NHibernate Linq查询 扩展增强 (第九篇) 在上一篇的Linq to NHibernate的介绍当中,全部是namespace NHibernate命名空间中的IQueryOver<TRoot, TSubType>接口提供的.IQueryOver<TRoot, TSubType>这个借口实际上会被翻译成条件查询(Criteria Queries). 实际上Linq to NHibernate更加强大.我们先引入命名空间NHibernate.Linq,这里面有Linq

mysql全文索引(三)查询扩展

查询扩展原理: 开启查询扩展(query expansion)时候,进行两次查询,第一次,查出用户给定的关键词对应的记录:第二次,用第一次查出的结果里的关键词,再去查一次,把两次的结果返回给用户 实验 mysql> select id,title,body from articles where match(title,body) against('fulltext' ) order by id asc; +----+-------------------------+-------------

应用程序框架实战二十三:基础查询扩展

上面两篇已经作好准备,本文将进行基础查询扩展.当使用了Entity Framework这样的ORM框架以后,我们查询的核心被集中在IQueryable的Where方法上. 如果UI需要通过姓名查询一个客户,会在UI上放置一个输入框作为客户姓名的查询条件.服务端接收以后通过Where方法进行过滤,如下所示,entities表示DbContext的子类. var queryable = entities.Customers.Where( t => t.Name == name ); 当然,也可以使用

Dapper 链式查询 扩展

Dapper 链式查询扩展 DapperSqlMaker   Github地址:https://github.com/mumumutou/DapperSqlMaker Demo: 查询       TestsDapperSqlMaker\DapperSqlMaker.Test\ SelectDapperSqlMakerTest.cs 添加       TestsDapperSqlMaker\DapperSqlMaker.Test\  InsertDapperSqlMakerTest.cs 更新 

ux.form.field.SearchField 列表、树形菜单查询扩展

1 //支持bind绑定store 2 //列表搜索扩展,支持本地查询 3 //支持树形菜单本地一级菜单查询 4 Ext.define('ux.form.field.SearchField', { 5 extend: 'Ext.form.field.Text', 6 alias: 'widget.uxSearchfield', 7 defaultBindProperty: 'store', 8 mixins: ['Ext.util.StoreHolder'], 9 triggers: { 10

简单树形查询

select empno 员工编号, ename 姓名, (prior empno) 主管编码, --取主管编号 mgr, --emp表中员工的主管编号,判断用,取出与查询的主管编码进行核对 (prior ename) as 主管姓名 --取对应的主管编号的姓名,取不到的主管为空 from emp start with empno = 7566 --指定开始编号 connect by (prior empno) = mgr; --建立树形连接,也就是递归的条件,上一级的编码等于本级的主管编码

[转载]oracle树形查询 start with connect by

一.简介 在oracle中start with connect by (prior) 用来对树形结构的数据进行查询.其中start with conditon 给出的是数据搜索范围, connect by后面给出了递归查询的条件,prior 关键字表示父数据,prior 条件表示子数据需要满足父数据的什么条件.如下start with id= '10001' connect by prior parent_id= id and prior num = 5表示查询id为10001,并且递归查询pa

EF下lambda与linq查询&amp;&amp;扩展方法

1. linq查询数据 WebTestDBEntities db = new WebTestDBEntities(); 1.1 linq查询所有列数据 var userInfoList = from u in db.UserInfo where u.ID == 10 select u; 1.2 linq查询部分列数据 var userInfoList = from u in db.UserInfo where u.ID >= 1 select new { Name = u.UserName, P