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

时间:2014-02-19 13:14:16

标签: c# sql sql-server tsql sql-server-2008-express

基于谢尔盖为我的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

3 个答案:

答案 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