2010-11-19 3 views
6

여기 게시 한 첫 번째 질문이므로 의도하지 않은 실수를 용서할 수 있습니다.SQL Server에서 집계되지 않은 데이터를 "피벗"

필자는 현재 커다란 정규화되지 않은 테이블을 가져 와서 4 개의 별도의 정규화 된 테이블로 나누었다. 이 보드에 대한 최종 목표는 이전 버전과의 호환성을 위해 정규화되지 않은 테이블을 모방 한 뷰를 만드는 것입니다.

내 시나리오의 단순화 된 스냅 샷, 내가 두 테이블에서 거짓말을 할 노력하고있어의 핵심 제공한다 : 그래서 나는 다음과 같은 쿼리를 실행하면

ASSOC_ROLE   ASSOCIATE 
----------   ---------- 
assoc_id (fk)  assoc_id (pk) 
role_id (fk)  last_name 
org_nbr (fk) 

을 ...

SELECT Assoc_Role.org_nbr, Assoc_Role.assoc_id, Associate.last_name, Assoc_Role.role_id 
FROM Assoc_Role INNER JOIN 
    Associate ON Assoc_Role.assoc_id = Associate.assoc_id 
WHERE Assoc_Role.org_nbr = '1AA' 

... 나는 다음과 같은 결과가 궁극적으로 내가 같이 보일 것이다 구축하고자하는 뷰를

org_nbr  assoc_id  last_name  role_id 
-------  --------  ---------  ------- 
1AA   1447   Cooper  1 
1AA   1448   Collins  3 
1AA   1448   Collins  4 
1AA   1448   Collins  5 
1AA   1449   Lynch   6 

을 설정할 수 :

org_nbr role1_ID role1_name role2_ID role2_name role3_ID role3_name role4_ID role4_name role5_ID role5_name role6_ID role6_name 
------- -------- ---------- -------- ---------- -------- ---------- -------- ---------- -------- ---------- -------- ---------- 
1AA  1447  Cooper  NULL  NULL   1448  Collins  1448  Collins  1448  Collins  1449  Lynch 

내 초기 생각은 PIVOT 명령을 사용하려고했지만, 나의 이해는 PIVOT은 집계의 어떤 종류를 필요로하고, 그 내 시나리오에 적합하지 않습니다. 또한 SELECT 절에서 CASE 명령을 사용하여 연주했지만 내 결과 집합을 하나의 레코드로 축소하지는 않습니다.

누군가가이 작업을 수행 할 수있는 방법을 밝힐 수 있기를 바랍니다. 누구에게 더 많은 정보가 필요한지 알려주세요. 감사!

스코틀랜드

답변

2

기본 번호-역할 데이터를 얻으려면, 우리는이 데이터를 가지고 각 role_id을 위해 각 org_nbr에 대해 별도의 행을 우리에게 줄 것이다

SELECT 
    org_nbr 
    , r1.assoc_id role1_ID 
    , r1.last_name role1_name 
    , r2.assoc_id role2_ID 
    , r2.last_name role2_name 
    , r3.assoc_id role3_ID 
    , r3.last_name role3_name 
    , r4.assoc_id role4_ID 
    , r4.last_name role4_name 
    , r5.assoc_id role5_ID 
    , r5.last_name role5_name 
    , r6.assoc_id role6_ID 
    , r6.last_name role6_name 
FROM 
    ASSOC_ROLE ar 
    LEFT JOIN ASSOCIATE r1 ON ar.role_id = 1 AND ar.assoc_id = r1.assoc_id 
    LEFT JOIN ASSOCIATE r2 ON ar.role_id = 2 AND ar.assoc_id = r2.assoc_id 
    LEFT JOIN ASSOCIATE r3 ON ar.role_id = 3 AND ar.assoc_id = r3.assoc_id 
    LEFT JOIN ASSOCIATE r4 ON ar.role_id = 4 AND ar.assoc_id = r4.assoc_id 
    LEFT JOIN ASSOCIATE r5 ON ar.role_id = 5 AND ar.assoc_id = r5.assoc_id 
    LEFT JOIN ASSOCIATE r6 ON ar.role_id = 6 AND ar.assoc_id = r6.assoc_id 

하지만 시작 수 ! 우리가 원하지 않는 것은 - 그래서 우리는 GROUP BY org_nbr이 필요합니다. 그렇다면 GROUP BY 또는 SELECT 목록의 모든 열에 대해 집계해야합니다. 트릭은 SQL 서버 이 원하는 결과를 제공하는 집계 함수를 제안하는 것입니다.

SELECT 
    org_nbr 
    , MIN(r1.assoc_id) role1_ID 
    , MIN(r1.last_name) role1_name 
    , MIN(r2.assoc_id) role2_ID 
    , MIN(r2.last_name) role2_name 
    , MIN(r3.assoc_id) role3_ID 
    , MIN(r3.last_name) role3_name 
    , MIN(r4.assoc_id) role4_ID 
    , MIN(r4.last_name) role4_name 
    , MIN(r5.assoc_id) role5_ID 
    , MIN(r5.last_name) role5_name 
    , MIN(r6.assoc_id) role6_ID 
    , MIN(r6.last_name) role6_name 
FROM 
    ASSOC_ROLE ar 
    LEFT JOIN ASSOCIATE r1 ON ar.role_id = 1 AND ar.assoc_id = r1.assoc_id 
    LEFT JOIN ASSOCIATE r2 ON ar.role_id = 2 AND ar.assoc_id = r2.assoc_id 
    LEFT JOIN ASSOCIATE r3 ON ar.role_id = 3 AND ar.assoc_id = r3.assoc_id 
    LEFT JOIN ASSOCIATE r4 ON ar.role_id = 4 AND ar.assoc_id = r4.assoc_id 
    LEFT JOIN ASSOCIATE r5 ON ar.role_id = 5 AND ar.assoc_id = r5.assoc_id 
    LEFT JOIN ASSOCIATE r6 ON ar.role_id = 6 AND ar.assoc_id = r6.assoc_id 
GROUP BY 
    org_nbr 

출력 : : 물론

org_nbr role1_ID role1_name role2_ID role2_name role3_ID role3_name role4_ID role4_name role5_ID role5_name role6_ID role6_name 
---------- ----------- ---------- ----------- ---------- ----------- ---------- ----------- ---------- ----------- ---------- ----------- ---------- 
1AA  1447  Cooper  NULL  NULL  1448  Collins 1448  Collins 1448  Collins 1449  Lynch 
Warning: Null value is eliminated by an aggregate or other SET operation. 

이 짧은 떨어질해야 최대 role_id 증가 ...

+0

흥미 롭습니다 ... 나는이 고급 수준에서 SQL 쿼리를 작성하는 것에 매우 익숙하므로 연속적으로 자체 테이블에 가입하는 것을 생각하지 않았지만 이것이 어떻게 작동하는지 명확하게 볼 수 있습니다. 내 다음 과제는 이것을 더 큰 쿼리에 통합하는 것이지만 이것은 나에게 훌륭한 출발점을 제공한다. 감사합니다. 하나의 질문에 관해서는 : "물론 이것은 최대 role_id가 증가하면 짧아 질 것입니다 ..." 더 많은 role_ID를 추가하면 해당 롤에 대해 설명해야합니다. 쿼리, 아니면 그 이상의 제안입니까? – ScottieByNature

+0

@ScottieByNature 최대 'role_ID'가 증가하면 두 가지 옵션이 있습니다. 변경 사항이 "최대 6 개 였지만 현재는 최대 9 개"라는 줄을 따라 가면 명확한 방법으로 쿼리에 쿼리를 추가해야합니다. 그러나 "이제는 임의의 수의 가능한 역할이있을 것"이라면 다른 접근 방식을 찾아야합니다.이 경우에는 @Chris Lively의 고려 사항이 적용되며 SQL 외부에서 수행하거나 동적 SQL, 또는 완전히 다른 것 - 당신은 여기에 와서 물어볼 수있다 : – AakashM

+0

Understood ... 많이 감사! – ScottieByNature

2

할 수 있다면, 나는 것이 경우, MIN는 일을 할 것입니다 정규 코드 (C#, vb, 뭐든간에)에서 이러한 유형의 피벗을 수행하는 것이 좋습니다.

SQL 서버에서 PIVOTing에는 많은 단점이 있습니다. 첫째, 7 개 또는 8 개가 넘는 항목이 쿼리에 소요되는 시간을 크게 늘릴 것입니다. 둘째, 잠재적 인 모든 ID를 미리 알기 위해 동적 SQL을 수행해야합니다. 셋째, 유지 관리가 어려울 것입니다.

AakashM의 대답에는 동일한 문제가 있습니다.

우리는 순수 SQL 설정에서이 작업을 수행하는 많은 다른 방법을 시도했습니다. 매우 제한된 피벗을 가진 작은 데이터 세트의 경우 잘 작동합니다. 그러나 역할 ID의 수는 이미 초과했습니다.

대신 데이터를 가져 와서 원하는 언어로 원하는 표를 만드십시오. 이 시점에서 데이터를 다른 SQL 테이블에 넣거나 갈 필요가있는 곳으로 보내십시오.

+0

공정한 제안 ... 그러나이 이전 버전과 호환되는보기를 빌드하려고하는 시스템은 Visual FoxPro를 기반으로합니다. 나는 SQL Server vs FoxPro에서 이러한 복잡성에 대한 시각을 쉽게 만들 수 있다고 가정했습니다. 이 작업을 계속하면서이 고려 사항을 염두에 둡니다. 감사! – ScottieByNature