2010-01-04 4 views
6

여러 쿼리의 정보를 단일 행에 넣으려고 할 때 까다로운 상황이 있습니다. 다음과 같은 데이터 유지두 개의 쿼리 (모두 합집합)를 하나의 행에 결합하려면 어떻게합니까?

CpuUage: 
    Time time 
    Group char(10) 
    Subsys char(4) 
    Jobs int 
    Cpu  int 

:

다음 표를 고려해 각 행이 예상된다 아래 오른쪽에

Time Group Subsys Jobs Cpu 
----- ------ ------ ---- --- 
00:00 group1 NORM  1 101 (grp1-norm) A1 
01:00 group1 SYS7  3 102 (grp1-sys7) A2 
01:00 group1 NORM  5 104 (grp1-norm) A1 
02:00 group1 NORM  7 108 (grp1-norm) A1 
02:00 group2 NORM  9 116 (grp2-norm) B1 
02:00 group3 SYS7  11 132 (grp3-sys7) C2 
03:00 group1 SYS7  13 164 (grp1-sys7) A2 
03:00 group1 IGNR  99 228 (grp1-ignr) -- 

마커를 (A1는 예를 들어) 보고서의 섹션은 관련되는.

각 사용자 그룹에 대해 단 하나의 단을 반환 할 수있는 쿼리가 필요합니다. JobsCpu의 값은 하위 시스템 ID에 따라 다른 열로 이동해야하며 하위 시스템 ID 인 SYS7NORM에만 관심이 있습니다. ,

  <------ 1 ------> <------ 2 ------> 
    Group NormJobs NormCpu Sys7Jobs Sys7Cpu 
    ------ -------- ------- -------- ------- 
A: group1  13  313  16  266 
B: group2   9  116   0  0 
C: group3   0  0  11  164 

우리의 오래된보고 솔루션의 (a union all와) 여러 쿼리를 실행할 수 있습니다 :

그래서, 예를 들어, 우리는합니다 (A/B/1/2 비트가 다시 위의 행에 상호 참조 수 있습니다) 다음이 필요합니다

Group NormJobs NormCpu Sys7Jobs Sys7Cpu 
------ -------- ------- -------- ------- 
group1  13  313   0  0 
group1   0  0  16  266 

함께 합병의 라인을 따라, :

있도록 다음 사후 처리는 행은 동일한 그룹 이름을 가진 사람을 결합하는

우리의 새로운 솔루션은 후 처리를 허용하지 않으며 모두 SQL 쿼리에서 수행되어야합니다.

SYS7 개의 행 (NORM 행)을 가진 그룹이있을 수도 있고 둘 다 같지 않을 수도 있음을 명심하십시오.이를 달성하는 가장 좋은 방법은 무엇입니까?

외부 선택 내에서 테이블을 하위 쿼리로 생각했지만 성능에 영향을 줄 수 있습니다. 내가 외부 쿼리 난 그냥에 대한 NORM 작업 이후 외부 쿼리를 할 수 없습니다 (NORM 및 SYS7 서브 시스템은 다음 모든 필드의 하위 쿼리를 실행 포함 할 거라고 이후

은 또한, 그 고통이 될 것입니다 단지 SYS7 행을 가진 그룹의 존재는 그렇게 잡히지 않을 것입니다.

실용적인 솔루션을 찾기 위해 왼쪽 중간 - 내측 - 오프사이드 조인 마법을 짜 넣을 수 있습니까?

벤더에 의존하지 않는 솔루션을 선호하지만, 벤더에 따라야하는 경우 플랫폼은 DB2입니다. 아직도, 다른 플랫폼은 적어도 나에게 무엇을 시도해야하는지에 대한 아이디어를 줄 수있어서 그들을 볼 수있어서 기쁩니다.그냥 빨리해야처럼

+0

것은, 내가보고 싶네 결과. 본능적으로, 나는 어떤 방법 으로든 또는 다른 어떤 방법으로 CASE 문장의 작업을 수행 할 것으로 기대한다. 나는. "groupname = g 및 subsys = s 인 경우 집계 (g, s)에 추가". 데이터 검색 측면에서 차이가 더 많을 것으로 기대합니다. 그러나 DBMS가 인덱스 정보를 활용하여 특정 그룹을 집계 할 때 필요한 비교 횟수를 줄일 수있는 가능성에 대해 공개적으로 말합니다. 물리적 정렬 순서 (클러스터 된 인덱스)가 (substys, groupname) 인 테스트 순열에 포함하는 것이 좋습니다. –

답변

13

내가 서브 쿼리의 문제를 이해하지 못한다는 것 같습니다 :

select 
    sub.gn as groupname, 
    sum(sub.nj) as NormJobs, sum(sun.nc) as NormCpu, 
    sum(sub.sj) as Sys7Jobs, sum(sub.sc) as Sys7Cpu 
    from (
     select 
      groupname as gn, 
      sum(jobs) as nj, sum(cpu) as nc, 
      0 as sj, 0 as sc 
     from tbl 
      where subsys = 'NORM' 
      group by groupname 
     union all select 
      groupname as gn, 
      0 as nj, 0 as nc, 
      sum(jobs) as sj, sum(cpu) as sc 
      from tbl 
      where subsys = 'SYS7' 
      group by groupname 
    ) as sub 
    group by sub.gn 
    order by 1 
+0

메인 쿼리에서 모든 그룹에 대해 하위 쿼리를 수행해야하는 것에 대해 우려했지만 솔루션에서이를 무시한 것으로 보입니다. 얼마나 많은 그룹이 있었는지 상관없이 두 개의 하위 쿼리 만있는 것처럼 보입니다. 귀하의 의견을 보내 주셔서 감사합니다. – paxdiablo

+0

+1을 수락합니다. 이 제품은 데이터베이스에서 단 두 번의 스 와이프로 트릭을 수행 했으므로 필요한만큼 빠릅니다. 필자는 DB2의 엄격한 요구 사항을 충족시키고 노동 조합을 조금 수정하기 위해 편집했습니다. – paxdiablo

4

그것은 일반적인 피벗 쿼리 - 여기 당신이 CASE statements 함께 할 것입니다 방법은 다음과 같습니다

SELECT t.group, 
     SUM(CASE 
      WHEN t.subsys = 'NORM' THEN t.jobs 
      ELSE NULL 
     END CASE) AS NormJobs, 
     SUM(CASE 
      WHEN t.subsys = 'NORM' THEN t.cpu 
      ELSE NULL 
     END CASE) AS NormCpu, 
     SUM(CASE 
      WHEN t.subsys = 'SYS7' THEN t.jobs 
      ELSE NULL 
     END CASE) AS Sys7Jobs, 
     SUM(CASE 
      WHEN t.subsys = 'SYS7' THEN t.cpu 
      ELSE NULL 
     END CASE) AS Sys7Cpu 
    FROM CPUUSAGE t 
GROUP BY t.group 

불행하게도, DB2의 CASE 문은 오라클/SQL 서버/MySQL은/​​포스트 그레스하지 않는 경우 END CASE로 종료해야합니다. 음, PLSQL은 END CASE을 지원합니다 ...

PIVOT syntax도 있으며, Oracle 11g 및 SQL Server 2005+에서도 지원됩니다.

+0

이것은 확실히 내 것보다 나은 해결책입니다. 나는이 '피봇 (pivot)'에 대해 몰랐으며, 공유해 주셔서 감사합니다! –

+0

subsys는 GROUP의 일부가 아니기 때문에 SUM이 전체 CASE를 캡슐화해야합니다. http://stackoverflow.com/questions/1997519/how-do-i-combine-two-queries-union-all-into-one-row/1997581#1997581 –

+0

@Craig : 고맙습니다. 고맙습니다. –

5

피벗 테이블 쿼리입니다. (당신이 추가 정보가 필요한 경우 있음에 검색 할 수 있습니다.)

원하는 쿼리 구조는 다음의 라인을 따라 뭔가 : 당신이 테스트를하고 해결책을 비교하면

SELECT groupname, 
     SUM(CASE WHEN subsys = 'NORM' THEN jobs ELSE 0 END) AS NormJobs, 
     SUM(CASE WHEN subsys = 'NORM' THEN cpu ELSE 0 END) AS NormCpu, 
     SUM(CASE WHEN subsys = 'SYS7' THEN jobs ELSE 0 END) AS Sys7Jobs, 
     SUM(CASE WHEN subsys = 'SYS7' THEN cpu ELSE 0 END) AS Sys7Cpu, 
     SUM(CASE WHEN subsys NOT IN ('NORM', 'SYS7') THEN jobs ELSE 0 END) AS OtherJobs, 
     SUM(CASE WHEN subsys NOT IN ('NORM', 'SYS7') THEN cpu ELSE 0 END) AS OtherCpu 
FROM ??? 
GROUP BY groupname 
+0

+1 : 정확한 SUM CASE 형식. –

+0

@ OMG의 답과 마찬가지로, 행 단위 함수에 대한 모든 걱정이 있습니다. 나는 그것을 조사해야 할 것이다. 나는 "OtherXxx"정보에 관심이 없기 때문에 마지막 두 개의 합계가 필요하다고 생각하지 않습니다. 단지 NORM과 SYS7입니다. 감사합니다. 성능 테스트를해야합니다. – paxdiablo

+0

+1 나를 도와 주려고하지만 @ BlueRaja의 솔루션은 DB에서 단 두 번의 스 와이프로 잘 작동하므로 다른 솔루션을 테스트 할 필요가 없었습니다. 이 행 단위 함수가 실제로 충분히 빠르다는 것을 한 번에 알아 내고 싶기 때문에 잠시 후에 테스트 할 것입니다. 당신의 도움을 주셔서 감사합니다. – paxdiablo

관련 문제