2010-02-11 4 views
2

DB 개월 : SQL Server 2005의동적 열 - SQL 서버 - 열

우리는이 방식으로 데이터가있는 테이블이 있습니다 데이터를 싶습니다

Project    Year  Jan     Feb     Mar     Apr     May     Jun     Jul     Aug     Sep     Oct     Nov     Dec 
-------------------- ----------- --------------------- --------------------- --------------------- --------------------- --------------------- --------------------- --------------------- --------------------- --------------------- --------------------- --------------------- --------------------- 
11-11079    2008  0.00     0.00     0.00     0.00     0.00     0.00     0.00     0.00     0.00     0.00     0.00     75244.90 
11-11079    2009  466.00    0.00     0.00     0.00     0.00     0.00     0.00     0.00     0.00     0.00     0.00     0.00 
11-11079    2010  855.00    0.00     0.00     0.00     0.00     0.00     0.00     0.00     0.00     0.00     0.00     0.00 
01-11052    2009  56131.00    0.00     36962.00    -61596.00    2428.00    84.00     0.00     0.00     0.00     0.00     0.00     0.00 

누군가가 한 행으로 표시 할을 전체 프로젝트 기둥은 앞으로 몇 년 동안 움직이는 지에 따라 동적으로 달라질 것입니다.

Project  Jan-2009  Feb-2009  Mar-2009  Apr-2009... Dec-2009  Jan-2010 
-------------- ------------ ------------ ------------ ----------- ------------ --------- 
11-11079  466.00  0.00   0.00   0.00  0.00   855.00  
01-11052  56131.00  0.00   36962.00  -61596.00 2428.00  0.00 

내가 날짜가 각 항목에 대해 하나 개의 컬럼에 채워집니다 많은 예제의 읽을 수 있지만 내가 개월이 열 이름있는 모든 경우를 발견하지 않았습니다 올해는 행에 있습니다 예로들 수 .

피벗 테이블이있는 동적 SQL?
아니면 SQL, 임시 테이블, 조인 및 공용체를 사용하여 꽤 광범위한 규모의 조작?
SSIS 피벗 테이블 기능 사용에 대한 의견이 있으십니까?

+1

제목이나 질문에 "MS SQL"이라는 용어를 사용하지 마십시오. 그런 제품이 없습니다. 이를 사용하면 검색이 귀하의 질문을 찾기 어렵고 SQL Server와 MySQL간에 혼동을 야기 할 수 있습니다. –

+0

heh - 저는 MSSQL을 MySQL –

+0

John으로 읽었 기 때문에 대답을 알고있는 tsql 질문을 무시했습니다. 그 이름은 가까이에 있고 혼란 스럽지만 여기서 게시하는 사람들에게는 공평합니다. Microsoft SQL Server는 어떤 방식으로 MSSQL이라고 불립니다. 바이너리 경로를 살펴보십시오. C : \ Program Files \ Microsoft SQL Server \ MSSQL10.TEST2008 \ MSSQL 또는 서비스 이름으로 MSSQL $ TEST2008을 생성하는 PowerShell> Get-Service는 적어도 나를 위해. – onupdatecascade

답변

4

데이터는 이미 피벗되었지만 다른 레벨로 선회되어야합니다. 이 문제를 해결하는 가장 좋은 방법은 먼저 피벗 해제 한 다음 올바른 피벗 레벨을 두 번째로 처리하는 것입니다.

1 단계 : 피벗 해제

당신은 SQL 2005 UNPIVOT 명령을 사용하거나 CROSS이 기술을 가입 할 수 있습니다. 다음 두 가지 예가 있습니다. 나는 물건을 단순하게 유지하기 위해 중간에 몇 달을 버렸다. 그냥에 추가합니다.

-- CROSS JOIN method (also works in SQL 2000) 
SELECT 
    P.Project, 
    Mo = 
     DateAdd(mm, 
     X.MonthNum, 
     DateAdd(yy, P.[Year] - 1900, '19000101') 
    ), 
    Amount = 
     CASE X.MonthNum 
     WHEN 0 THEN Jan 
     WHEN 1 THEN Feb 
     WHEN 11 THEN Dec 
     END 
FROM 
    ProjectData P 
    CROSS JOIN (
     SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 11 
    ) X (MonthNum) 

을 각 행이 12 번 반복 한 다음 CASE 문이 잘 피봇 팅 데이터를 떠나, 각 행에 대해 단 일개월 꺼내서.

-- UNPIVOT method 
SELECT 
    P.Project, 
    Mo = 
     DateAdd(mm, 
      Convert(int, P.MonthNum), 
      DateAdd(yy, P.[Year] - 1900, '19000101') 
     ), 
    P.Amount 
FROM 
    (
     SELECT Project, [Year], [0] = Jan, [1] = Feb, [11] = Dec 
     FROM ProjectData 
    ) X UNPIVOT (Amount FOR MonthNum IN ([0], [1], [11])) P 

DROP TABLE ProjectData 

어느 방법도 항상 확실한 성능 우승자가 아닙니다. 때로는 다른 하나보다 잘 작동합니다 (피벗 된 데이터에 따라 다름). UNPIVOT 메서드는 CROSS JOIN이 수행하지 않는 실행 계획의 필터를 사용합니다.

2 단계 : 피벗 다시

이제, 피봇 팅 데이터를 사용하는 방법에 대해 설명합니다.당신은 누군가이 이것을 소비 할 것이라고 말하지 않았지만, 어떤 종류의 출력 파일에 데이터를 넣어야하므로 SQL Server 2005와 함께 제공되는 SSRS (SQL Server Reporting Services)를 사용하여 제안합니다. 추가 비용없이.

Matrix 보고서 개체를 사용하여 위 쿼리 중 하나를 피벗 시키면됩니다. 이 개체는 보고서 실행시 열 레이블에 적용 할 데이터 값을 기쁘게 결정하고 사용자가 필요로하는 것과 똑같은 소리를냅니다. 원하는 형식으로 날짜의 서식을 지정하는 열을 추가하면 Mo 열로 정렬 할 수 있지만 새 식을 열 레이블로 사용할 수 있습니다.

SSRS에는 다양한 형식 및 예약 옵션이 있습니다. 예를 들어 Excel 파일을 이메일로 보내거나 웹 페이지를 파일 공유에 저장할 수 있습니다.

아무 것도 남겨 두지 않으면 알려주세요.

USE tempdb 

CREATE TABLE ProjectData (
    Project varchar(10), 
    [Year] int, 
    Jan decimal(15, 2), 
    Feb decimal(15, 2), 
    Dec decimal(15, 2) 
) 

SET NOCOUNT ON 

INSERT ProjectData VALUES ('11-11079', 2008, 0.0, 0.0, 75244.90) 
INSERT ProjectData VALUES ('11-11079', 2009, 466.0, 0.0, 0.0) 
INSERT ProjectData VALUES ('11-11079', 2010, 855.0, 0.0, 0.0) 
INSERT ProjectData VALUES ('01-11052', 2009, 56131.0, 0.0, 0.0) 
+0

원래 질문을 게시 한 후 오후에 데이터를 쳐다 보면서 데이터가 이미 선회되었습니다. 나는 그것 위에서 빠른 unpivot를 달리게되는 순간, 빛이 계속되었고 내가 원하는 방식으로 그것을 만들 수 있었다. 그래서 당신의 테크닉은 내가 끝내는 길입니다! – ichauvin

-1

중첩 된 while 루프 및 일부 동적 SQL을 사용하여 작업 할 수 있다고 생각합니다. 최종 테이블을 저장할 수 없거나 매월 모든 열을 다시 생성해야하는 경우에는 느린 솔루션입니다. 그러나 그것이 단지 첨가물이라면 나쁜 것이 아닐 수도 있습니다. 어쨌든, 다음과 같이하면됩니다.

  1. 아웃 루프가 가장 오래된 연도를 선택합니다.
  2. 내부 루프가 첫 번째 달을 선택합니다.
  3. 내부 내부 루프 - 이름이 - 인 열을 테이블에 추가하십시오. 매년 외부 루프를 통해 매달
  4. 반복 처리에 대한 내부 루프를 통해 동적 SQL
  5. 반복 처리와 열 -
  6. 내부 내부 루프 - 새로운 대한 모든 정보와 업데이트 테이블.
+0

-1. 죄송합니다. RandomBen. 루프를 반대로 회전하고 다시 피벗 할 수있는 명확하고 쉬운 세트 기반 솔루션을 사용할 수있는 루프는 지원되지 않습니다. 루프가있는 성능은 절대적으로 끔찍할 것입니다. – ErikE

0

내가, 소스가 here이 함께 도울 수 pivot_query라는 이름의 저장된 프로 시저 쓴 : 액션에서 위의 코드를보고 싶은 사람들을위한

, 여기 당신을 위해 몇 가지 작성 스크립트입니다 , 원시 데이터가있는 예는 here입니다.

With your data: 

create table ProjectData 
    (
    Project      varchar(20), 
    [Year]      Integer, 
    Jan       decimal(12,2), 
    Feb       decimal(12,2), 
    Mar       decimal(12,2), 
    Apr       decimal(12,2), 
    May       decimal(12,2), 
    Jun       decimal(12,2), 
    Jul       decimal(12,2), 
    Aug       decimal(12,2), 
    Sep       decimal(12,2), 
    Oct       decimal(12,2), 
    Nov       decimal(12,2), 
    Dec       decimal(12,2) 
    ); 

insert into ProjectData values ('11-11079',2008, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 75244.90); 
insert into ProjectData values ('11-11079',2009, 466.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00); 
insert into ProjectData values ('11-11079',2010, 855.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00) ; 
insert into ProjectData values ('01-11052',2009, 56131.00, 0.00, 36962.00, -61596.00, 2428.00, 84.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00); 

declare @mySQL varchar(MAX) 

set @mySQL = 'select * from ProjectData' 

exec pivot_query @mySQL, 'Project', 'Year', 'max(Jan) Jan,max(Feb) Feb,max(Mar) Mar,max(Apr) Apr,max(Jun) Jun,max(Jul) Jul,max(Aug) Aug,max(Sep) Sep,max(Oct) Oct,max(Nov) Nov,max(Dec) Dec' 

Results: 
Project    2008_Jan  2008_Feb  2008_Mar  2008_Apr  2008_Jun  2008_Jul  2008_Aug  2008_Sep  2008_Oct  2008_Nov  2008_Dec  2009_Jan  2009_Feb  2009_Mar  2009_Apr  2009_Jun  2009_Jul  2009_Aug  2009_Sep  2009_Oct  2009_Nov  2009_Dec  2010_Jan  2010_Feb  2010_Mar  2010_Apr  2010_Jun  2010_Jul  2010_Aug  2010_Sep  2010_Oct  2010_Nov  2010_Dec 
-------------------- ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ 
01-11052    NULL   NULL   NULL   NULL   NULL   NULL   NULL   NULL   NULL   NULL   NULL   56131.00  .00   36962.00  -61596.00 84.00  .00   .00   .00   .00   .00   .00   NULL   NULL   NULL   NULL   NULL   NULL   NULL   NULL   NULL   NULL   NULL 
11-11079    .00   .00   .00   .00   .00   .00   .00   .00   .00   .00   75244.90  466.00  .00   .00   .00   .00   .00   .00   .00   .00   .00   .00   855.00  .00   .00   .00   .00   .00   .00   .00   .00   .00   .00 

하지 정확한하지만 무척 가깝습니다. :-)

+0

5 월을 추가하는 것을 잊어 버렸으므로, 글을 올리도록 게시물을 편집 할 수 없습니다. :-) –

+0

신성한 crud, Ron. 세트 기반 코드 및 기존 SQL Server 도구를 사용하여 문제를 해결할 수있는 경우 왜 방대한 양의 절차 코드를 사용합니까? – ErikE

+0

피벗 열의 값을 알 필요없이 모든 검색어에 대해 일반적으로 작동합니다. "피벗 팅 (pivoted)"스타일 보고서를 통해 개발자에게 많은 시간을 절약 할 수있었습니다. 나는 이것을 위해서 쓰지 않았다. :-) –