2013-08-02 6 views
14

SQL Server 2008R2에 다음 원본 및 대상 테이블이 있습니다. TSQL에서 피벗을 수행하여 소스에서 대상에 도달하려면 어떻게합니까? SourceTblSQL Server 하나의 열을 기반으로 여러 열을 피벗

empId empIndex empState empStDate empEndDate 
======================================================== 
10  1   AL   1/1/2012  12/1/2012 
10  2   FL   2/1/2012  2/1/2013 
15  1   FL   3/20/2012 1/1/2099 

DestTbl

empId empState1 empState1StDate empState1EndDt empState2 empState2StDate empState2EndDt 
========================================================================================================= 
10  AL   1/1/2012   12/1/2012   FL   2/1/2012   2/1/2013 
15  FL   3/20/2012   1/1/2099   NULL  NULL    NULL 

는 empIndex 어떻게 든 피벗에 도움이 될 것으로 기대.

+0

피벗은 msaccess에서 변환이라고도합니다. 당신의 질문은 결과 셀에 텍스트 (정수가 아님)가 있다는 점에서 독특합니다. 집계 함수가 여전히 적용되어야합니다. MIN()은 단 하나의 텍스트 값이있을 때에도 Text 값에 대해 잘 수행해야합니다. – hamish

답변

23

SQL Server를 사용하고 있으므로 여러 가지 방법으로 행을 열로 변환 할 수 있습니다. CASE 식과 함께 집계 함수를 사용할 수 있습니다.

select empid, 
    max(case when empindex = 1 then empstate end) empState1, 
    max(case when empindex = 1 then empStDate end) empStDate1, 
    max(case when empindex = 1 then empEndDate end) empEndDate1, 
    max(case when empindex = 2 then empstate end) empState2, 
    max(case when empindex = 2 then empStDate end) empStDate2, 
    max(case when empindex = 2 then empEndDate end) empEndDate2 
from sourcetbl 
group by empid; 

SQL Fiddle with Demo을 참조하십시오.

결과를 얻기 위해 PIVOT 함수를 사용하려면 먼저 empState, empStDateempEndDate 열을 unpivoting하여 여러 행을 먼저 표시하는 것이 좋습니다. 코드가 될 것입니다 당신은 UNPIVOT 기능을 사용하거나 CROSS는 데이터를 변환에 적용

select empid, col+cast(empindex as varchar(10)) col, value 
from sourcetbl 
cross apply 
(
    select 'empstate', empstate union all 
    select 'empstdate', convert(varchar(10), empstdate, 120) union all 
    select 'empenddate', convert(varchar(10), empenddate, 120) 
) c (col, value); 

Demo를 참조하십시오. 데이터가 피봇 팅되면 최종 코드가 될 수 있도록, 당신은 PIVOT 기능을 적용 할 수

select empid, 
    empState1, empStDate1, empEndDate1, 
    empState2, empStDate2, empEndDate2 
from 
(
    select empid, col+cast(empindex as varchar(10)) col, value 
    from sourcetbl 
    cross apply 
    (
    select 'empstate', empstate union all 
    select 'empstdate', convert(varchar(10), empstdate, 120) union all 
    select 'empenddate', convert(varchar(10), empenddate, 120) 
) c (col, value) 
) d 
pivot 
(
    max(value) 
    for col in (empState1, empStDate1, empEndDate1, 
       empState2, empStDate2, empEndDate2) 
) piv; 

SQL Fiddle with Demo를 참조하십시오. 당신이 empindex 제한된 수의 경우

는 버전 위

목은 잘 작동합니다 있지만 경우에하는 당신은 동적 SQL 사용할 수 있습니다

DECLARE @cols AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX) 

select @cols = STUFF((SELECT ',' + QUOTENAME(col+cast(empindex as varchar(10))) 
        from SourceTbl 
        cross apply 
        (
         select 'empstate', 1 union all 
         select 'empstdate', 2 union all 
         select 'empenddate', 3 
        ) c (col, so) 
        group by col, so, empindex 
        order by empindex, so 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT empid,' + @cols + ' 
      from 
      (
       select empid, col+cast(empindex as varchar(10)) col, value 
       from sourcetbl 
       cross apply 
       (
        select ''empstate'', empstate union all 
        select ''empstdate'', convert(varchar(10), empstdate, 120) union all 
        select ''empenddate'', convert(varchar(10), empenddate, 120) 
       ) c (col, value) 
      ) x 
      pivot 
      (
       max(value) 
       for col in (' + @cols + ') 
      ) p ' 

execute sp_executesql @query; 

참조 SQL을 Fiddle with Demo

당신은 삽입하려면 다음 쿼리를 사용할 수 있습니다

DestTbl에 있거나 데이터를이 형식으로 저장하는 대신 이제 원하는 결과를 얻기위한 쿼리를 사용할 수 있습니다.

이 쿼리는 형식으로 데이터를 배치 : 내가 상상했던 것보다

| EMPID | EMPSTATE1 | EMPSTDATE1 | EMPENDDATE1 | EMPSTATE2 | EMPSTDATE2 | EMPENDDATE2 | 
--------------------------------------------------------------------------------------- 
| 10 |  AL | 2012-01-01 | 2012-12-01 |  FL | 2012-02-01 | 2013-02-01 | 
| 15 |  FL | 2012-03-20 | 2099-01-01 | (null) |  (null) |  (null) | 
+0

당신의 노력에 감사드립니다. 그것은 또한 내 문제를 해결합니다. 고마워요 @bluefeet –

+0

많이 사용하기 전에 FOR XML을 보았습니다. 그러나 kudos와 * thumbsup *을 사용하는 것이 가장 좋습니다 : STUFF QUOTENAME 및 NVARCHAR (MAX)를 PIVOT에 넣었습니다. MSACCESS는이 TRANSFORM을 호출합니다 (왜 그 명령 SQL 서버를 만들지 않았다) – hamish

-1

와우이 더 복잡했다,하지만 난 그게 잘 작동하는 거죠! 감사. 이것은 나의 최종 버전이었다. TextKey에는 열로 바꿀 데이터가 들어 있고 TextValue는 각 셀 내부에서 끝나는 값입니다.

DECLARE @cols AS NVARCHAR(MAX), 
     @query AS NVARCHAR(MAX) 


select @cols = STUFF((SELECT distinct ', ' + QUOTENAME(TextKey) 
        from #SourceTbl 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT FromEntityID, DisplayName, ' + @cols + ' 
       FROM 
       (
        select FromEntityID, DisplayName, TextKey, TextValue 
        from #SourceTbl 
      ) x 
       pivot 
       (
        min(TextValue) 
        for TextKey in (' + @cols + ') 
      ) p 
       ORDER BY FromEntityID 
       ' 

execute(@query) 
관련 문제