Nur*_*ely 5 performance sql-server hierarchy sql-server-2012 query-performance
我有一个包含文件夹路径的表。该表包含四列:
DirID - 文件夹的 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'
Run Code Online (Sandbox Code Playgroud)
所以我们需要找到以下数据:
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'
Run Code Online (Sandbox Code Playgroud)
注释:
此 dbfiddle 中的扩展示例数据和预期结果。
这个问题是 Stack Overflow 问题Find missing hierarchy Folders (Paths) in a table的延续。我们的问题还包括以粗体显示的第 4 条评论。
我看到有一种叫做(从 SQL Server 2008 开始)的新类型hierarchyid,我认为它可能对我们有帮助。你怎么认为?
我会尝试这样的事情:
'A\B\C\D\E'变成'A\B\C\D')并在表中添加这些新文件路径,如果它们还没有的话。初始化:
-- step 0
CREATE TABLE filepaths
( BaseDirID int NOT NULL,
DirLevel int NOT NULL,
DisplayPath varchar(1000) NOT NULL, -- adjust the size according to your data,
ReverseDisplayPath varchar(1000) NOT NULL,
Iteration int NOT NULL,
PRIMARY KEY (Iteration, ReverseDisplayPath),
UNIQUE (ReverseDisplayPath)
) ;
INSERT INTO filepaths
( BaseDirID, DirLevel, DisplayPath, ReverseDisplayPath, Iteration )
SELECT
BaseDirID, DirLevel, DisplayPath, reverse(DisplayPath), 0
FROM
existing_table ;
Run Code Online (Sandbox Code Playgroud)
和迭代:
DECLARE @new_items bigint ;
DECLARE @iter int ;
SET @iter = 0 ;
-- repeat
repeat:
INSERT INTO filepaths
(BaseDirID, DirLevel, DisplayPath, ReverseDisplayPath, Iteration)
SELECT DISTINCT
f.BaseDirID, f.DirLevel - 1, reverse(r.rdp), r.rdp, @iter + 1
FROM
filepaths AS f
CROSS APPLY
( SELECT substring(f.ReverseDisplayPath,
1 + charindex('\', f.ReverseDisplayPath),
1000) AS rdp
) AS r
WHERE
f.Iteration = @iter
AND f.DirLevel > 1
AND NOT EXISTS
( SELECT *
FROM filepaths AS ex
WHERE ex.ReverseDisplayPath = r.rdp
) ;
SET @new_items = @@ROWCOUNT ;
SET @iter = @iter + 1 ;
-- until new_items = 0
IF (@new_items > 0) GOTO repeat;
Run Code Online (Sandbox Code Playgroud)
该过程完成后,您可以通过简单的查询仅获取丢失的文件路径:
SELECT DisplayPath FROM filepaths
WHERE Iteration > 0
ORDER BY DisplayPath ;
Run Code Online (Sandbox Code Playgroud)
在dbfiddle.uk 中测试。
反向字符串不是严格需要的,但它们简化了字符串的拆分。你可以不用它们(以及更复杂的代码)。您也可以只将反向路径存储在新的filepaths表中,当迭代完成时,将它们再次反向到目标表(我猜是现有的表或您希望它们去的任何地方)。
整个事情也可以通过一次完成 - 使用递归 CTE - 但我不知道这是否会或多或少有效。