基于Sergey为我的c#问题提供的出色解决方案:过滤掉以字符串开头的路径字符串,我离开了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
通常,最好将数据库中作为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 的路径。 像这样:
SELECT Paths.Path
FROM Paths
WHERE Paths.Username = @guy
And Len(Path) - Len(Replace(Path, '', '')) = 1
ORDER BY Paths.Path DESC
这假定您的路径的格式一致。 如果您的根路径还包含尾随反斜杠,则此解决方案将不适合您。 基本上,此查询将仅返回带有单个反斜杠的路径。
您能否简单地使用 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