基于谢尔盖为我的c#问题提供的出色解决方案:Filter out path strings beginning with strings,我离开去为T-SQL制作类似的东西。 我可以重构这个在内存表中使用而不是游标,但我真的想看看是否有一个基于集合的方法可以用来实现相同的目标。
场景:我在数据库中有路径,如下所示:C:\ Users,C:\ Users \ cheese,D:\ Shadow \ stuff,D:\ Shadow。我需要过滤离开最根本路径的路径(例如,在上面的4中,只留下C:\ Users,D:\ Shadow)
这就是我现在所拥有的:
ALTER PROCEDURE [dbo].[GetPaths]
@guy NVARCHAR(MAX)
AS
DECLARE
@tempPath NVARCHAR(MAX) = '',
@Path NVARCHAR (MAX),
@filteredPath TABLE (FilteredPath NVARCHAR(MAX))
BEGIN
SET NOCOUNT ON;
IF (@guy IS NOT NULL)
BEGIN
DECLARE C Cursor FOR
SELECT Paths.Path
WHERE
Paths.Username = @guy
ORDER BY Paths.Path DESC
OPEN C
FETCH NEXT FROM C INTO @Path
WHILE @@Fetch_Status=0 BEGIN
IF (CHARINDEX(@tempPath, @Path = 0)
BEGIN
INSERT INTO @filteredPath(FilteredPath)
VALUES (@Path)
END
SET @tempPath = @Path
FETCH NEXT FROM C into @Path
END
CLOSE C
DEALLOCATE C
SELECT * FROM @filteredPath
END
END
答案 0 :(得分:1)
通常最好在数据库中执行select
查询而不是使用游标。我相信以下内容将有效地使用Paths(path)
上的索引:
select p.*
from Paths p
where not exists (select 1
from Paths p2
where p.path like p2.path + '%' and
p.path <> p2.path
);
(不幸的是,我今天无法测试。)
顺便说一下,你的游标表达式缺少from
子句,这可能与它不起作用的原因有关。
答案 1 :(得分:1)
这是一个想法。
如果你取走路径的长度并减去反斜杠的路径长度,你只需要值为1的路径。这样的东西:
SELECT Paths.Path
FROM Paths
WHERE Paths.Username = @guy
And Len(Path) - Len(Replace(Path, '\', '')) = 1
ORDER BY Paths.Path DESC
这假设您的路径都是一致的格式。如果您的根路径也包含尾部反斜杠,则此解决方案将不适合您。基本上,此查询只返回带有单个反斜杠的路径。
答案 2 :(得分:1)
您是否可以简单地使用CASE
语句将其重写为查询,以区分“根”级别的路径和具有子目录的路径:
SELECT DISTINCT
CASE (CHARINDEX('\', Path, CHARINDEX('\', Path) + 1))
WHEN 0 THEN Path
ELSE SUBSTRING(Path, 1, (CHARINDEX('\', Path, CHARINDEX('\', Path) + 1) - 1))
END
FROM Paths
WHERE Username = @guy