SQL:在拆分层次结构中查找缺少的文件夹路径

时间:2017-05-16 19:39:15

标签: sql sql-server sql-server-2012 sql-server-performance

我有一个包含文件夹路径的表。 此表包含四列:DirIDBaseDirIDDirLevelDisplayPathDirID - 文件夹的ID。 BaseDirID - 层次结构中第一个文件夹的ID。因此,同一层次结构中的所有文件夹(路径)在此列中共享相同的值。 DirLevel - 文件夹的深度。 DisplayPath - 文件夹的路径。

我需要找到所有"差距"在层次结构中的这些文件夹之间。

示例数据,例如:

DirID BaseDirID DirLevel DisplayPath
1   1  1  'A'
2   1  3  'A\B\C'
3   1  5  'A\B\C\D\E'
4   1  3  'A\B\F'
5   1  5  'A\B\F\G\H'
6   2  1  'U'
7   2  3  'U\V\W'
8   2  5  'U\V\W\X\Y'
9   2  3  'U\V\M'
10  2  5  'U\V\M\L\O'

所以我们需要找到以下数据:

BaseDirID DisplayPath
1   'A\B'
1   'A\B\C\D'
1   'A\B\F\G'
2   'U\V'
2   'U\V\W\X'
2   'U\V\M\L'

评论:

一个。此表包含超过250,000个文件夹记录,因此我们寻求最有效的方法,否则脚本会长时间停留,我们没有时间。

湾我没有所有文件夹的列表。我所拥有的是" root"文件夹和"叶子"文件夹,我需要找到"差距"他们之间的层次结构。

℃。该表可以包含多个层次结构,我们需要找到"间隙"在所有层次结构中。

d。每个层次结构都可以拆分,正如您在示例数据中看到的那样,第一个层次结构将从“A \ B&B”中分割为两个文件夹路径。夹: ' A \ B \ C'和' A \ B \ F'。 第二层次结构分为两个文件夹路径,来自&U; V'文件夹:' U \ V \ W'和' U \ V \ M'。 我们需要找到所有"差距"即使在层次结构分裂的情况下也是如此。

即sql server版本是:SQL 2012 SP3。

此问题是以下链接中提出的问题的延续问题:SQL: Find missing hierarchy Folders (Paths) in a table 我们的问题还包括以粗体显示的第4条评论。

我看到有一个新的列类型叫做#34; hierarchyid" (从sql server 2008开始),我认为这可能对我们有所帮助 - https://docs.microsoft.com/en-us/sql/t-sql/data-types/hierarchyid-data-type-method-reference 你觉得怎么样?

提前致谢。

1 个答案:

答案 0 :(得分:1)

使用此添加的路径.content{ width:128px; height:96px; background-size: 100% 100%; background-repeat: no-repeat;} img.wf{background-size:640px 480px;} div.wf{display:inline-block;} span.wf{display:inline-block;} } 在路径中显示多个缺少的文件夹:

(11,2,'U\V\Z\L\O\Q\R\S\T')

rextester演示:http://rextester.com/CEVGZ96613

返回:

with cte as (
select BaseDirID, DisplayPath = left(DisplayPath,len(DisplayPath)-charindex('\',reverse(DisplayPath)))
from t
where DirLevel > 1
  and not exists (
  select 1 
  from t i
  where t.BaseDirId = i.BaseDirId
    and i.DisplayPath = left(t.DisplayPath,len(t.DisplayPath)-charindex('\',reverse(t.DisplayPath)))
    )
union all 
select BaseDirID, DisplayPath = left(DisplayPath,len(DisplayPath)-charindex('\',reverse(DisplayPath)))
from cte t
where not exists (
  select 1 
  from t i
  where t.BaseDirId = i.BaseDirId
    and i.DisplayPath = left(t.DisplayPath,len(t.DisplayPath)-charindex('\',reverse(t.DisplayPath)))                                                   
    )
)
select distinct * 
from cte