2010-06-01 4 views
1

필자는 피봇 팅이 필요한 매우 간단한 쿼리를 가지고 있지만 필자가 문헌에서 읽은 피벗 테이블로 전환하는 방법을 알지 못했습니다. 내가 읽은 모든 것은 하드 코딩 된 열을 포함하거나 너무 복잡합니다. 그것은 더 간단해야만합니다. 아니면 CTE를 이해할 수 없습니다.이 간단한 사례에 대한 피벗 쿼리는 어떻게 만듭니 까?

쿼리는 액세스 권한이있는 사용자 이름 및 클라이언트의 목록입니다. 그래서 저는 다음과 같은 것을 가지고 있습니다 :

user client 
1 a 
1 b 
1 c 
2 a 
2 d 
3 a 
3 d 
3 e 
3 f 

총 클라이언트 수는 약 20 정도가 될 수 있습니다. 일부 사용자는 모든 클라이언트에 액세스 할 수 있고 다른 사용자는 하나 또는 두 개의 클라이언트에만 액세스 할 수 있습니다. 내가보고 싶은 것은 : 사용자 테이블, 클라이언트 테이블, 그들의 고객과 사용자를 통합하는 상호 참조 테이블 (권한) :

user a b c d e f 
1 x x x 
2 x x 
3 x x x x 

이 세 개의 테이블을 포함한다.

나는 다음과 같은 것을 시도했지만 분명히 작동하지 않는다 (심지어 컴파일도).

with usersclients(user_name, clients, client_code) 
as 
(
select users.user_name 
from clients cli 
    left join 
    (select u.user_id, user_name, c.client_id, client_code, client_name 
    from permissions p inner join clients c on p.client_id = c.client_id 
    inner join users u on u.user_id = p.user_id 
) user 
    on user.client_id = cli.client_id 
) 
select * 
from usersclients 
pivot (max(client_code) for client_code in (select client_code from clients)) as P 

실마리를 알 수있는 단서!

답변

2

SQL 서버에서 피벗의 각 열에 명시 적으로 이름을 지정해야한다고 생각합니다. 그래서, 원래 쿼리에서 다음 코드는 허용되지 않습니다 :

for client_code in (select client_code from clients)

명시 적으로 각 클라이언트 코드의 이름을해야합니다.

편집 : 여기에 귀하의 예에 맞는 샘플 피벗입니다 :

WITH Permit (Usr, Client) AS 
(
    SELECT 1, 'a' UNION ALL 
    SELECT 1, 'b' UNION ALL 
    SELECT 1, 'c' UNION ALL 
    SELECT 2, 'a' UNION ALL 
    SELECT 2, 'd' UNION ALL 
    SELECT 3, 'a' UNION ALL 
    SELECT 3, 'd' UNION ALL 
    SELECT 3, 'e' UNION ALL 
    SELECT 3, 'f' 
) 
SELECT p.* 
FROM Permit 
    PIVOT (MAX(Client) FOR Client IN (a, b, c, d, e, f)) p 

을 편집 : 여기에 동적 SQL 옵션입니다; TVF에 넣을 수도 있습니다.

--source table 
CREATE TABLE #Permit (Usr int, Client char(1)); 
INSERT INTO #Permit (Usr, Client) 
SELECT 1, 'a' UNION ALL 
SELECT 1, 'b' UNION ALL 
SELECT 1, 'c' UNION ALL 
SELECT 2, 'a' UNION ALL 
SELECT 2, 'd' UNION ALL 
SELECT 3, 'a' UNION ALL 
SELECT 3, 'd' UNION ALL 
SELECT 3, 'e' UNION ALL 
SELECT 3, 'f'; 


DECLARE @Command nvarchar(max); 
SET @Command = ''; 

--prepare the list of columns 
SELECT @Command = @Command + ', ' + CONVERT(nvarchar(10), Client) 
FROM (SELECT DISTINCT Client FROM #Permit) x; 

--chop the extra leading comma off 
SET @Command = SUBSTRING(@Command, 3, LEN(@Command)); 

--prepare the rest of the pivot command 
SET @Command = N' 
SELECT p.* 
FROM #Permit 
    PIVOT (MAX(Client) FOR Client IN (' + @Command + ')) p'; 

--execute the command 
EXEC sp_executesql @Command; 


DROP TABLE #Permit; 
+0

감사합니다. Michael이 모든 열의 이름을 명시 적으로 지정해야하는 이유입니다. 그것은 수십 명의 고객을 보유 할 수있는 진정한 PITA입니다 ... – Larry

+0

동의합니다. 쿼리를 문자열로 구성하고 클라이언트가 많은 경우'sp_executesql'을 사용할 수 있습니다. 곧 내 답변을 업데이트하겠습니다. –

+0

그래서 유일한 방법은 동적 SQL을 사용하고 있습니까? 나는 그 선을 따라 몇 가지 예를 보았다. 위의 방법을 시도했지만 불행히도 수천 명의 사용자가 있습니다! 코드 작성에는 시간이 걸릴 것입니다. 다른 대답은 사용자/클라이언트 목록을 Excel로 가져와 Excel에서 피벗 테이블을 만들도록하는 것입니다. Excel은 그런 종류의 것이 더 나은 것 같습니다. – Larry

관련 문제