2014-02-19 1 views
0

Sergey가 제공 한 훌륭한 솔루션을 기반으로 여기에 Filter out path strings beginning with strings의 C# 질문이 생겼습니다. T-SQL과 비슷한 기술을 사용하려고했습니다. 커서를 메모리 테이블에서 사용하도록 리팩터링 할 수 있지만 같은 목표를 달성하기 위해 취할 수있는 세트 기반 접근 방식이 있는지 확인하고 싶습니다.SQL 저장 프로 시저의 최상위 경로 만 남겨주세요.

시나리오 : db : C : \ Users, C : \ Users \ cheese, D : \ Shadow \ stuff, D : \ Shadow와 같은 경로가 있습니다. 나는 단지 rootmost 것들을 떠나 경로를 필터링해야 (예를 들어, 위의 4에서 만 C를 떠나 : \ 사용자를, D를 : \ 그림자)이 내가 지금 무엇을 가지고

:

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

당신은 SQL 서버의 어떤 버전을 사용하고 있습니다 ? –

+0

@GordonLinoff 2008 Express – zaitsman

+0

여기에서 분할 기능을 사용하지 마십시오. http : //stackoverflow.com/questions/2647/split-string-in-sql – KumarHarsh

답변

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 절과 그 힘이 없습니다 왜 작동하지 않는지와 관련이 있습니다.

+0

링크에서 dbo.fn_Split을 사용하십시오. 이것은 최고입니다! 나는 그것을 할 수 있다면 2 번이나 올릴 것이다. 이것은 (실행 계획을 기반으로 한) 다른 사람들이 제공 한 솔루션보다 약 2 배 빠르며, 내가 생각해 낸 성능의 약 5 %입니다. 정말 고맙습니다! – zaitsman

1

생각해보십시오. 이것은 가정

SELECT Paths.Path 
FROM Paths 
WHERE Paths.Username = @guy 
     And Len(Path) - Len(Replace(Path, '\', '')) = 1 
ORDER BY Paths.Path DESC 

: 당신이 경로의 길이을 제거 백 슬래시 경로의 길이를 빼면

, 당신은이 같은 1 뭔가의 값을 가진 사람을 원한다 귀하의 경로가 모두 일관되게 형식화되어 있는지 확인하십시오. 후행 슬래시가 포함 된 루트 경로가있는 경우이 솔루션은 작동하지 않습니다. 기본적으로이 쿼리는 단일 백 슬래시가있는 경로 만 반환합니다.

+0

이것은 작동합니다 (또한 입력을 제어 할 때 나에게도 도움이됩니다). 제 질문에 대답 해 주셔서 감사합니다. – zaitsman

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 
+0

그 위대한 접근 방식은 그것에 대해 생각하지 않았다. – zaitsman