2009-12-13 3 views
1

나는 알아낼 수없는 SQL 문에 대해 작업 중입니다. 결과를 사전 순으로 정렬해야하지만, "부모"순서대로 "아이들"이 필요합니다. 다음은 내가 작업하고있는 테이블과 데이터의 간단한 예입니다. 모든 비 관련 열이 제거되었습니다. SQL Server 2005를 사용하고 있습니다.이 작업을 수행하는 쉬운 방법이 있습니까?SQL Ordering Hiarchy

tblCats 
======= 

idCat | fldCatName  | idParent 
-------------------------------------- 
1  | Some Category  | null 
2  | A Category  | null 
3  | Top Category  | null 
4  | A Sub Cat   | 1 
5  | Sub Cat1   | 1 
6  | Another Cat  | 2 
7  | Last Cat   | 3 
8  | Sub Sub Cat  | 5 


Results of Sql Statement: 

A Category 
Another Cat 
Some Category 
A Sub Cat1 
Sub Cat 1 
    Sub Sub Cat 
Top Category 
Last Cat 

(결과의 앞에 둔 공간은, 내 SQL 결과에 접두사 공간을 원하지 않는 결과의 이해에 추가 할 수 있습니다. 그 결과는이 순서에 있어야합니다.)

+0

이것은 잠시 동안 할 수 있기를 바랬던 것입니다. 특히 CTE 재귀를 사용하면 좋겠지 만, 나는 그것을 결코 관리하지 못했습니다. 응답이 있는지에 관심이 있습니다. –

+0

나는 'A Category'와 'Some Category'가 결과에서 반전 된 것 같아. – Ray

+0

예, 실제로 했어요. 나는 그것을 잡아서 고쳤다. – stephenbayer

답변

3

다음과 같이 계층 적 쿼리를 사용하여 수행 할 수 있습니다.

t-sql에서 PAD funciton이 없기 때문에 훨씬 더 복잡해 보입니다. 계층 구조의 시드는 부모가없는 범주입니다. 우리가 선택한 네 번째 열은 알파벳순으로 순위가 매겨집니다 (문자열과 패딩으로 변환 됨). 그런 다음 우리는 이것을 자녀들과 결합시킵니다. 각각의 재귀에서, 아이들은 모두 같은 레벨에있게 될 것이므로 파티셔닝 할 필요없이 알파벳 순으로 순위를 매길 수 있습니다. 우리는 이러한 순위를 나무 아래로 연결하여 그 순서대로 정렬 할 수 있습니다. 데이터와

;WITH Hierarchy AS (
    SELECT 
     idCat, fldCatName, idParent, 
     CAST(RIGHT('00000'+ 
        CAST(ROW_NUMBER() OVER (ORDER BY fldCatName) AS varchar(8)) 
        , 5) 
      AS varchar(256)) AS strPath 
    FROM Category 
    WHERE idParent IS NULL 

    UNION ALL 

    SELECT 
     c.idCat, c.fldCatName, c.idParent, 
     CAST(h.strPath + 
      CAST(RIGHT('00000'+ 
          CAST(ROW_NUMBER() OVER (ORDER BY c.fldCatName) AS varchar(8)) 
         , 5) AS varchar(16)) 
      AS varchar(256)) 
    FROM Hierarchy h 
     INNER JOIN Category c ON c.idParent = h.idCat 
) 
SELECT idCat, fldCatName, idParent, strPath 
FROM Hierarchy 
ORDER BY strPath 

:

idCat fldCatName  idParent strPath 
------------------------------------------------ 
    2 A Category  NULL  00001 
    6 Another Category 2  0000100001 
    1 Some Category  NULL  00002 
    4 A Sub Category 1  0000200001 
    5 Sub Cat1   1  0000200002 
    8 Sub Sub Category 5  000020000200001 
    3 Top Category  NULL  00003 
    7 Last Category  3  0000300001 
+0

그냥 테스트 해봤는데 작동합니다! 감사합니다 .. 쿼리는 약간 시간이 걸리지 만 재귀를 사용하면 예상됩니다. – stephenbayer

+0

예, 두렵습니다. 문자열 조작도 도움이되지 않습니다. – Paul

1

나는이 문제에 대한 SQL Server (또는 Ansi-SQL) 고유의 지원을 알지 못합니다.

임시 테이블과 재귀 저장 프로 시저를 "쉬운"방법이라고 생각하지 않습니까? J

+0

는 나에게 약간의 아이디어를 준다, 나는 오늘 밤 그것을 해결할 것이다. 사실 DAL에서 코드 측면의 데이터를 조작하여 해결책을 찾았습니다. 전체 세트를 가져 와서 부모를 기반으로하는 패딩 된 키를 사용하여 해시 테이블을 만든 다음 키를 정렬합니다. 조금 비효율적이지만 몇백 개 밖에 없습니다. – stephenbayer

+0

재귀 WITH 절은 계층 적 쿼리를 처리하는 ANSI 방식입니다. –

+0

그냥 말해도 될까요 - 여기의 모든 서브 쿼리 솔루션은 성능상의 메모리 내장 임시 테이블 생성과 다를 바 없습니다. 다 괜찮아요.하지만 IMHO를 사용하면 재귀 SQL 문을 작성해야 할 때 모든 논리를 애플리케이션 코드로 옮길 수 있습니다.시나리오에 따라 성능 측면에서 누락되지 않는 좋은 기회가 있습니다. 코드가 명확하고 이해하기 쉽고 동료 프로그래머와 후임 직원이 영원히 감사 할 것입니다. –

0

바울의 대답은 우수합니다,하지만 난 당신을위한 또 다른 아이디어를 던질 거라 생각 했어요. Joe Celko는 Smarties에 대한 SQL (29 장)에서이 문제에 대한 해결책을 제시합니다. 여기에는 계층 구조 정보를 포함하는 별도의 테이블을 유지 관리해야합니다. 삽입, 업데이트 및 삭제는 약간 복잡하지만 선택은 매우 빠릅니다.

죄송합니다. 게시 할 링크 나 코드가 없지만이 책에 대한 액세스 권한이 있으면 도움이 될 것입니다.

2

CTE에서 수행 할 수 있습니다.

With MyCats (CatName, CatId, CatLevel, SortValue) 
    As 
    (Select fldCatName CatName, idCat CatId, 
     0 Level, Cast(fldCatName As varChar(200)) SortValue 
     From tblCats 
     Where idParent Is Null 
     Union All 
     Select c.fldCatName CatName, c.idCat CatID, 
     CatLevel + 1 CatLevel, 
     Cast(SortValue + '\' + fldCatName as varChar(200)) SortValue 
     From tblCats c Join MyCats p 
      On p.idCat = c.idParent) 

    Select CatName, CatId, CatLevel, SortValue 
    From MyCats 
    Order By SortValue 

편집 : (아래 폴스 '의견을 들으은) (200)의 경우 문자 다음, 가장 긴 연결된 문자열 "경로"를 개최 필요한만큼 높은에 값을 변경하는 것만으로는 충분하지 않습니다 ... 당신은 할 수 있습니다 8000만큼 높습니다.

+0

그건 좋은 해결책이야. 내 것보다 빨리 달릴거야. 계층 구조가 연결 필드 이름이 200자를 넘는 깊이까지 도달하지 않도록주의해야합니다. – Paul

+0

당신은 각 레벨에서 이름을 나타내는 추상 문자열을 작성하고 있습니다 ... 더 짧은 문자열이지만 왜 솔루션이 느려 집니까? –

+0

나는 여분의 캐스팅이 약간 느려질 것이라고 생각했지만, 그것에 대해 생각해 보면, 사물의 웅장한 구성에서 그다지 차이를 만들지 않을 것입니다. – Paul