2013-07-23 9 views
11

Aşağıdaki sorguda daha iyi bir yaklaşım olup olmadığını görmek istiyorum. Yapmaya çalıştığım, tarihe göre istatistikleri derleyen bir özet raporu oluşturmak.SQL Sorgusu - SUM (Birden çok sütun için CASE DAHA SONRA 1 0)

Bu, diğer bir dizi sütun ve diğer istatistikleri için mantık olduğu gibi (bir raporda kullanılan) Sorgunun sadece bir örnektir
SELECT CAST(Detail.ReceiptDate AS DATE) AS 'DATE' 
, SUM(CASE WHEN Detail.Type = 'TotalMailed' THEN 1 ELSE 0 END) AS 'TOTALMAILED' 
, SUM(CASE WHEN Detail.Type = 'TotalReturnMail' THEN 1 ELSE 0 END) AS 'TOTALUNDELINOTICESRECEIVED' 
, SUM(CASE WHEN Detail.Type = 'TraceReturnedMail' THEN 1 ELSE 0 END) AS 'TRACEUNDELNOTICESRECEIVED' 
FROM 
(
select SentDate AS 'ReceiptDate', 'TotalMailed' AS 'Type' 
from MailDataExtract 
where sentdate is not null 
UNION ALL 
select MDE.ReturnMailDate AS 'ReceiptDate', 'TotalReturnMail' AS 'Type' 
from MailDataExtract MDE 
where MDE.ReturnMailDate is not null 
UNION ALL 
select MDE.ReturnMailDate AS 'ReceiptDate', 'TraceReturnedMail' AS 'Type' 
from MailDataExtract MDE 
    inner join DTSharedData.dbo.ScanData SD ON SD.ScanDataID = MDE.ReturnScanDataID 
where MDE.ReturnMailDate is not null AND SD.ReturnMailTypeID = 1 
) AS Detail 
GROUP BY CAST(Detail.ReceiptDate AS DATE) 
ORDER BY 1 

yol daha karmaşıktır. Bu tür bir bilgiyi edinme/bu tür raporları yazma konusunda daha zarif bir yaklaşım var mı?

+0

bu proc veya bir görünüm, yoksa başka bir şey mi? Temel olarak, değişkenleri tanıtabilir ve birden çok ifade çalıştırabilir misiniz, yoksa sadece büyük bir '' '' '' '' '' '' '' '' '' '' 'deyimidir? –

+0

Bu bir SSRS raporu için kullanılacak bir proc, bu yüzden bir sonuç kümesi (sağa?) – MickJuice

+0

Evet, sonuç olarak büyük bir 'select' dönmek zorunda olarak aslında bir select deyimi olması gerekecek. Sonuç olarak, bir prok uygulamasından bu yana, sorgunuzu daha küçük, daha basit parçalara ayırabilmeniz ve değişkenleri değişkenlere atayabildiğinizden emin olabilirsiniz. Bu okunabilirlik açısından büyük bir fark yaratabilir. Örneğin, bu üç alt soruyu birleştirmek veya gruplandırmak yerine, değişkenlere özetlenmiş sonuçlar atayan üç küçük bağımsız sorguya sahip olabilirsiniz, ardından geri dönüş sorgunuz için bu değişkenleri seçmeniz yeterlidir. Potansiyel olarak okumak ve anlamak ve muhtemelen daha iyi performans için çok daha kolay. –

cevap

8

Ben şu şekillerde sorguyu değiştirecek:

  1. alt sorgular içinde toplama yapın. Bu, group by'un en iyileştirilmesine yönelik tablo hakkında daha fazla bilgi alabilir.
  2. İkinci ve üçüncü alt sorguları birleştirin. Aynı sütunda toplanıyorlar. Bu, tüm verilerin kullanılabilir olduğundan emin olmak için left outer join kullanılmasını gerektirir.
  3. count(<fieldname>) kullanarak, is null ile karşılaştırmaları ortadan kaldırabilirsiniz. Bu, ikinci ve üçüncü hesaplanan değerler için önemlidir.
  4. İkinci ve üçüncü sorguları birleştirmek için mde tablosundan bir kimlik girilmelidir. Bunlar mde.mdeid'u kullanır.

aşağıdaki sürüm union all kullanarak örnek aşağıdaki gibidir:

SELECT CAST(Detail.ReceiptDate AS DATE) AS "Date", 
     SUM(TOTALMAILED) as TotalMailed, 
     SUM(TOTALUNDELINOTICESRECEIVED) as TOTALUNDELINOTICESRECEIVED, 
     SUM(TRACEUNDELNOTICESRECEIVED) as TRACEUNDELNOTICESRECEIVED 
FROM ((select SentDate AS "ReceiptDate", COUNT(*) as TotalMailed, 
       NULL as TOTALUNDELINOTICESRECEIVED, NULL as TRACEUNDELNOTICESRECEIVED 
     from MailDataExtract 
     where SentDate is not null 
     group by SentDate 
    ) union all 
     (select MDE.ReturnMailDate AS ReceiptDate, 0, 
       COUNT(distinct mde.mdeid) as TOTALUNDELINOTICESRECEIVED, 
       SUM(case when sd.ReturnMailTypeId = 1 then 1 else 0 end) as TRACEUNDELNOTICESRECEIVED 
     from MailDataExtract MDE left outer join 
      DTSharedData.dbo.ScanData SD 
      ON SD.ScanDataID = MDE.ReturnScanDataID 
     group by MDE.ReturnMailDate; 
    ) 
    ) detail 
GROUP BY CAST(Detail.ReceiptDate AS DATE) 
ORDER BY 1; 

benzer bir şey full outer join kullanarak yok şu:

SELECT coalesce(sd.ReceiptDate, mde.ReceiptDate) AS "Date", 
     sd.TotalMailed, mde.TOTALUNDELINOTICESRECEIVED, 
     mde.TRACEUNDELNOTICESRECEIVED 
FROM (select cast(SentDate as date) AS "ReceiptDate", COUNT(*) as TotalMailed 
     from MailDataExtract 
     where SentDate is not null 
     group by cast(SentDate as date) 
    ) sd full outer join 
    (select cast(MDE.ReturnMailDate as date) AS ReceiptDate, 
      COUNT(distinct mde.mdeID) as TOTALUNDELINOTICESRECEIVED, 
      SUM(case when sd.ReturnMailTypeId = 1 then 1 else 0 end) as TRACEUNDELNOTICESRECEIVED 
    from MailDataExtract MDE left outer join 
      DTSharedData.dbo.ScanData SD 
      ON SD.ScanDataID = MDE.ReturnScanDataID 
    group by cast(MDE.ReturnMailDate as date) 
    ) mde 
    on sd.ReceiptDate = mde.ReceiptDate 
ORDER BY 1; 
0

Gruplama yapmak için bir alt sorgu oluşturmalısınız. Bu durumda, iç alt sorgu birkaç satır döndürür ve bir CASE ifadesine gerek yoktur. Yani bu daha hızlı olacak düşünüyorum:

select Detail.ReceiptDate AS 'DATE', 
     SUM(TotalMailed), 
     SUM(TotalReturnMail), 
     SUM(TraceReturnedMail) 

from 
(

select SentDate AS 'ReceiptDate', 
     count('TotalMailed') AS TotalMailed, 
     0 as TotalReturnMail, 
     0 as TraceReturnedMail 
from MailDataExtract 
where sentdate is not null 
GROUP BY SentDate 

UNION ALL 
select MDE.ReturnMailDate AS 'ReceiptDate', 
     0 AS TotalMailed, 
     count(TotalReturnMail) as TotalReturnMail, 
     0 as TraceReturnedMail 
from MailDataExtract MDE 
where MDE.ReturnMailDate is not null 
GROUP BY MDE.ReturnMailDate 

UNION ALL 

select MDE.ReturnMailDate AS 'ReceiptDate', 
     0 AS TotalMailed, 
     0 as TotalReturnMail, 
     count(TraceReturnedMail) as TraceReturnedMail 

from MailDataExtract MDE 
    inner join DTSharedData.dbo.ScanData SD 
     ON SD.ScanDataID = MDE.ReturnScanDataID 
    where MDE.ReturnMailDate is not null AND SD.ReturnMailTypeID = 1 
GROUP BY MDE.ReturnMailDate 

) as Detail 
GROUP BY Detail.ReceiptDate 
ORDER BY 1 
İlgili konular