sql - 在 T-SQL 中具体化嵌套集层次结构的路径

标签 sql sql-server tsql nested-sets

我有一张包含我公司会计科目表详细信息的表格 - 这些数据基本上存储在嵌套集中(在 SQL Server 2014 上),每条记录都有一个左右 anchor - 没有父 ID。

示例数据:

ID  LeftAnchor  RightAnchor  Name     
 1           0           25  Root     
 2           1           16  Group 1  
 3           2            9  Group 1.1
 4           3            4  Account 1
 5           5            6  Account 2
 6           7            8  Account 3
 7          10           15  Group 1.2
 8          11           12  Account 4
 9          13           14  Account 5
10          17           24  Group 2  
11          18           23  Group 2.1
12          19           20  Account 1
13          21           22  Account 1

我需要具体化每条记录的路径,以便我的输出如下所示:

ID  LeftAnchor  RightAnchor  Name       MaterializedPath
 1           0           25  Root       Root
 2           1           16  Group 1    Root > Group 1
 3           2            9  Group 1.1  Root > Group 1 > Group 1.1
 4           3            4  Account 1  Root > Group 1 > Group 1.1 > Account 1
 5           5            6  Account 2  Root > Group 1 > Group 1.1 > Account 2
 6           7            8  Account 3  Root > Group 1 > Group 1.1 > Account 3
 7          10           15  Group 1.2  Root > Group 1 > Group 1.2
 8          11           12  Account 4  Root > Group 1 > Group 1.2 > Acount 4
 9          13           14  Account 5  Root > Group 1 > Group 1.2 > Account 5
10          17           24  Group 2    Root > Group 2
11          18           23  Group 2.1  Root > Group 2 > Group 2.1
12          19           20  Account 1  Root > Group 2 > Group 2.1 > Account 10
13          21           22  Account 1  Root > Group 2 > Group 2.1 > Account 11

虽然我已经设法使用 CTE 实现了这一点,但查询速度非常慢。在输出中输出大约 1200 条记录,运行仅需​​不到两分钟。

这是我的代码的简化版本:

;with accounts as
(
    -- Chart of Accounts
    select AccountId, LeftAnchor, RightAnchor, Name
    from ChartOfAccounts
    -- dirty great where clause snipped
)
, parents as
(
    -- Work out the Parent Nodes
    select c.AccountId, p.AccountId [ParentId]
    from accounts c
    left join accounts p on (p.LeftAnchor = (
        select max(i.LeftAnchor)
        from accounts i
        where i.LeftAnchor<c.LeftAnchor
        and i.RightAnchor>c.RightAnchor
    ))
)
, path as
(
    -- Calculate the Account path for each node

    -- Root Node
    select c.AccountId, c.LeftAnchor, c.RightAnchor, 0 [Level], convert(varchar(max), c.name) [MaterializedPath]
    from accounts c
    where c.LeftAnchor = (select min(LeftAnchor) from chart)

    union all

    -- Children
    select n.AccountId, n.LeftAnchor, n.RightAnchor, p.level+1, p.path + ' > ' + n.name
    from accounts n
    inner join parents x on (n.AccountId=x.AccountId)
    inner join path p on (x.ParentId=p.AccountId)
)
select * from path order by LeftAnchor

理想情况下,此查询只需要几秒钟(最多)即可运行。我无法对数据库本身(只读连接)进行任何更改,所以任何人都可以想出更好的方法来编写此查询吗?

最佳答案

在您发表评论后,我意识到不需要 CTE...您已经有了范围键。

示例

Select A.*
      ,Path = Replace(Path,'&gt;','>')
 From YourTable A
 Cross Apply (
                Select Path = Stuff((Select ' > ' +Name 
                                      From (
                                            Select LeftAnchor,Name
                                             From  YourTable
                                             Where A.LeftAnchor between LeftAnchor and RightAnchor 
                                           ) B1
                                      Order By LeftAnchor
                                      For XML Path (''))
                                    ,1,6,'')
             ) B
 Order By LeftAnchor

返回

enter image description here

关于sql - 在 T-SQL 中具体化嵌套集层次结构的路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45055020/

相关文章:

sql - Oracle 中的 TO_Char 数字格式模型

sql - 将值从实数值列复制到 SQL 中的小数值列

sql - 使用 SSMS 编辑模式在 SQL 表中添加当前日期时间

sql - 在 SQL 中分组之前合并结果

sql-server - 当过滤器是逗号分隔的值列表时如何过滤记录

sql-server - SQL查找最长序列

sql - 临时存储列数可变的表

mysql - 无法在 MySQL 触发器中将变量设置为 CURRENT_DATE()

c# - 我无法弄清楚的有关 ExecuteScalar 的错误

SQL Server Geography数据类型在线上最近的点