2014-07-11 1 views
4

에서 상위/하위 데이터베이스에서 각 ID에 대한 관련 데이터를 얻기I은 ​​다음 표와 함께 작동 TSQL

-- USER TABLE -- 
User_ID | Manager_ID | Code 
1  | null  | ABC 
2  | 1   | DEF 
3  | 2   | HIJ 
4  | null  | ABC 
나는 코드가 "소유"하는 경우 각 사용자에 대한 관련 코드를 알고 필요

여부 . 코드가 같은 행에있을 때 이와 관련된 코드는 사용자가 "소유"입니다

USER_ID = 1 : 소유 코드 = ABC

그러나 나는 또한에 대한 관련 코드를 알 필요가 각 사용자는 Manager_ID -> User_ID 계층 구조로 구성됩니다. 이 계층 구조에는 최대 깊이가 없습니다.

USER_ID = 1 : 관련 코드 =, 나는 다음과 같은 결과를 얻을 싶습니다 HIJ (USER_ID 2에 의해) 및 내 예에서

(USER_ID 3가) DEF

SELECT User_ID, Code, 1 as IsOwner 
FROM User 
: 소유 코드에 대한
User_ID | Code | IsOwner 
1  | ABC | 1 
1  | DEF | 0 
1  | HIJ | 0 
2  | DEF | 1 
2  | HIJ | 0 
3  | HIJ | 1 
4  | ABC | 1 

는 간단하다, 나는 다음과 같은 질문을했다

하지만 계층 구조에 대한 몇 가지 문제를 만났습니다. 인터넷에서 예제를 찾으려고했지만 "레벨"또는 "카운트"가있는 요청 만 볼 수 있으며 모든 관련 코드를 검색하는 방법을 알지 못합니다.

나는

USE MyBD 
GO 
WITH MyCTE (Manager_ID, User_ID, Code, IsOwned) 
AS 
(
    SELECT Manager_ID, User_ID, Code, 1 as IsOwned 
    FROM User 
    WHERE Manager_ID IS NULL 
    UNION ALL 
    SELECT u.Manager_ID, u.User_ID, u.Code, 1 as IsOwned 
    FROM User AS u 
    INNER JOIN Managers AS d 
     ON u.Manager_ID = d.User_ID 
) 
SELECT Manager_ID, User_ID, Code, IsOwned 
FROM Managers 
GO 

는 당신이 날 각 사용자 및 소유권과 관련된 모든 코드를 얻을 수 있도록 할 수 ... 공통 테이블 표현식을보고 같은 쿼리를 시도했지만 내가 뭔가를 놓친 것 같아?

+0

최대 계층 구조가 있습니까? –

+0

@ RaphaëlAlthaus 아니요 최대 깊이가 없습니다. 내 게시물을 편집합니다. – Alex

답변

2

내가 찾은 유일한 방법은 가입 변경, 마지막으로, 연결과 계층 구조의 추적을 유지하는 것입니다, 다음 연결된 값을 분할합니다.

WITH Managers 
AS 
(
    SELECT Manager_ID, User_ID, Code, cast(User_ID as varchar(max)) as hierarchy 
    FROM Users 
    WHERE Manager_ID IS NULL 
    UNION ALL 
    SELECT u.Manager_ID, u.User_ID, u.Code, d.hierarchy + case when d.hierarchy <> '' then '_' else '' end + cast(u.user_id as varchar) 
    FROM Users AS u 
    INNER JOIN Managers AS d 
     ON u.Manager_ID = d.User_ID 
) 

SELECT splitdata, Code, case when splitdata = user_id then 1 else 0 end as IsOwner 

FROM 
(
SELECT *, 
-- this part, for readability, should be replace by a split function 
cast('<X>'+replace(F.hierarchy,'_','</X><X>')+'</X>' as XML) as xmlfilter from Managers F 
)a 
CROSS APPLY 
( 
SELECT cast(fdata.D.value('.','varchar(50)') as int) as splitdata 
FROM a.xmlfilter.nodes('X') as fdata(D)) s 
order by splitdata, Code 

sqlfiddle을 참조하십시오.

sqlfiddle에는 이해를 돕기 위해 CTE 결과 만있는 부분도 있습니다.

EDIT (소유자 기능에 대한), 여기에 톰 챈 틀러에 의해 수정으로, 이전 버전의 오해가있을 수 있습니다으로

!

+0

이것은 아주 좋습니다. 비슷한 일을하고 있었지만 이것이 더 낫다고 생각합니다. –

+0

@TomChantler 흠, 슬프게도 hierarhcy의 깊이가 더 깊어지면 슬프게도 일부 레벨이 반환되지 않을 것이라고 생각합니다 ... –

+0

다음을 확인하십시오 : http://sqlfiddle.com/#!6/a1e242/4 추가 정보 당신이 말한 것처럼 작동하지 않는 계층 구조를 만들었지 만 새로운 "owner"컬럼을'1'에서'CASE WHEN topManager = User_Id THEN 1 ELSE 0 END'로 변경하여 사용자가 최고 관리자 . 어쩌면 당신은 당신의 대답을 업데이트 할 수 있습니까? –

1

검색어에 약간의 수정을가했습니다. 다음을 시도해보십시오. 첫 번째 쿼리에서 where 조건을 제거했습니다. 관리자가 아닌 모든 사용자에 대해 계층 구조를 가져와야하기 때문입니다. 그리고 또한이 조건을

;WITH MyCTE (Manager_ID, User_ID, Code, IsOwned) 
AS 
(
    SELECT User_ID, User_ID, Code, 1 as IsOwned 
    FROM [User] 

    UNION ALL 
    SELECT d.Manager_ID, u.User_ID, u.Code, 0 as IsOwned 
    FROM [User] AS u 
    INNER JOIN MyCTE AS d 
     ON u.Manager_ID = d.User_ID 
) 
SELECT Manager_ID, User_ID, Code, IsOwned 
FROM MyCTE ORDER BY Manager_ID,Code; 
+0

답장을 보내 주셔서 감사합니다. 귀하의 질문을 시도했으며 변경 사항을 적용했습니다. 나는 계층 구조를 얻을 수 있지만 위에서 아래로 ...나의 예에서는 (3, HIJ, 1) (3, DEF, 0)과 (3, ABC, 0)을 얻는다. 너무 가깝지만 이러한 CTE를 이해하는 데 어려움을 겪고 있습니다. – Alex

+0

쿼리를 업데이트 할 수 있습니까? –