2010-01-04 20 views
6

Birden çok sorgudan bilgi almak için tek bir satırda zor bir durum var. aşağıdaki verileri tutanİki sorguyu (tümünü birleştir) bir satırda nasıl birleştiririm?

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

:

aşağıdaki tabloyu düşünün her satır gerekiyordu bunun altında sağda

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) -- 

belirteçleri (A1 örneğin) raporunda bölümlerdir etkilemek.

Her kullanıcı grubu için tek bir satırı döndürebilen ancak bir şartla bir sorguya ihtiyacım var. Jobs ve Cpu için değerler, alt sistem kimliğine bağlı olarak farklı sütunlara gitmeli ve yalnızca SYS7 ve NORM altsistem kimlikleriyle ilgileniyorum. ,

  <------ 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 

Bizim eski raporlama çözümü (a union all ile) birden fazla sorgu çalıştırabilir:

Yani, örneğin, biz (A/B/1/2 bit geri yukarıdaki satırlara bir çapraz referans vardır) aşağıdaki gerek

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

birleştirilmiş edildi çizgisinde:

, böylece daha sonra işlem sonrası sıraları, aynı grup adı kombinleyecektik

Maalesef, yeni çözümümüz işlem sonrası işleme izin vermiyor ve bunların hepsi SQL sorgusunda yapılmalıdır.

SYS7 satır, NORM satır içeren grupların olabileceğini akılda tutarak, ya bunu başarmanın en iyi yolu nedir?

Tablonun bir dış seçim içinden sorgulanmasını düşündüm, ancak bu performansın bir sonucu olabilir. Ben dış sorgu Sadece için NORM işler beri dış sorgu yapamaz (NORM ve SYS7 alt sistemleri daha sonra her alanı için bir alt sorgu çalıştırmak dahil etmesi gerekir çünkü

ek olarak, bu acıyı olurdu sadece SYS7 satırlı bir grubun varlığı bu şekilde yakalanamazdı).

Uygun bir çözüm bulmak için sol orta-iç-off-add-magic sihrinizden herhangi birini örebilir misiniz?

Satıcıdan bağımsız bir çözüm tercih ederim, ancak satıcıya özel bir şekilde gitmeniz gerekirse, platform DB2'dir. Yine de, diğer platformlar en azından bana neyi denemeleri gerektiğiyle ilgili bir fikir verebilir, ben de onları görmekten mutlu olurum.böylesi daha hızlı olması gerektiği gibi

+0

, görmek ilgi duyarım sonuçlar. İçgüdüsel olarak, bir şekilde herhangi bir çözümün CASE bildiriminin görevini yerine getirmesini beklerim. Yani "Groupname = g ve subsys = s ise o zaman agrega ekleyin (g, s)". Veri alma açısından bir fark daha beklerim. Bununla birlikte, bir DBMS'nin belirli grupları toplarken gerekli olan karşılaştırma sayısını azaltmak için dizin bilgisini kullanabilme olasılığına açığım. Fiziksel sıralama düzeninizin (kümelenmiş dizin) (alt kümeler, grup adı) olduğu test permütasyonlarınıza dahil etmenizi öneririm. –

cevap

13

Ben alt sorgulama ile sorunu anlamıyorum, öyle görünüyor ki:

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

Ana sorguda her grup için bir alt sorgu yapmak zorunda olmakla ilgili endişelerim vardı, ancak çözümünüz buna ters düşmüş görünüyor. Görünüşe bakılırsa, kaç tane grubun olduğuna bakılmaksızın sadece iki alt sorgu olacaktı. Girişiniz için teşekkürler, kesinlikle bir şans vereceğim. – paxdiablo

+0

+1 ve kabul edin. Bu, veritabanında sadece iki swipe ile hile yaptı ve ihtiyaçları için yeterince hızlı. Bununla birlikte, DB2'nin zorlu şartlarını eşleştirmek ve sendikayı biraz değiştirmek için düzenledim. – paxdiablo

4

Tipik bir eksen sorgusu var - burada CASE statements yapardım nasıl:

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 

Maalesef DB2'nin DURUM ifadeleri Oracle/SQL Server/MySQL/Postgres değil yaptığında END CASE, ile sona gerekir. Peki, PLSQL aynı zamanda Oracle 11g ve SQL Server 2005+ üzerinde de desteklenen PIVOT syntax da var.

+0

Bu kesinlikle benimkinden daha iyi bir çözümdür; Bu 'pivot' un farkında değildim, paylaştığın için teşekkürler! –

+0

SUM'nuz, alt bölümün bir parçası olmadığı için SUM'nuzun tamamını kapsüllemelidir. Bkz. Http://stackoverflow.com/questions/1997519/how-do-i-combine-two-queries-union-all-into-one-row/1997581#1997581 –

+0

@Craig: Düzeltildi, thanx. –

5

Bu, bir pivot tablo sorgusudur. (Daha fazla bilgi gerekiyorsa bu konuda arama yapın.)

istediğiniz sorgu yapısı aşağıdaki çizgisinde bir şeydir: Eğer testi yapmak ve çözümler karşılaştırırsanız

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: Doğru SUM CASE formatı için. –

+0

@ OMG'nin cevabında olduğu gibi, sıradaki tüm işlevler için endişeleniyorum. Kontrol etmeliyim. Son iki toplamın gerekli olacağını düşünmüyorum çünkü "OtherXxx" bilgisini umursamıyorum, sadece NORM ve SYS7. Teşekkürler, biraz performans testi yapmam lazım. Bana yardımcı olmak için – paxdiablo

+0

+1 ama @ BlueRaja'nın çözümü DB'de sadece iki swipe iyi çalıştı, böylece diğer çözümleri test etmem gerekti. Bir keresinde ve satır başına bu fonksiyonların gerçekten yeterince hızlı olup olmadığını öğrenmek istediğimden kısa bir süre sonra test etmeye çalışacağım. Yardım ettiğin için teşekkür ederim. – paxdiablo

İlgili konular