在 sql 存储过程中仅保留最根路径



基于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

最新更新