13

I'm looking to see if there is a better approach to the query below. What I'm trying to do is create a summary report, compiling stats by date.

 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   

This is only a sample of the query (which is used in a report) as there are a number of other columns and the logic for the other stats are way more complicated. Is there a more elegant approach to getting this kind of information/writing this kind of report?

4

2 回答 2

9

我将通过以下方式更改查询:

  1. 在子查询中进行聚合。这可以利用有关表的更多信息来优化group by.
  2. 合并第二个和第三个子查询。它们聚集在同一列上。这需要使用 aleft outer join来确保所有数据都可用。
  3. 通过使用count(<fieldname>),您可以消除与 的比较is null。这对于第二个和第三个计算值很重要。
  4. 要结合第二个和第三个查询,它需要从mde表中计算一个 id。这些使用mde.mdeid

以下版本使用以下版本遵循您的示例union all

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;

以下使用以下方法执行类似操作full outer join

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;
于 2013-07-23T13:44:32.577 回答
0

我认为你应该做一个子查询来进行分组。在这种情况下,内部子查询返回几行,您不需要 CASE 语句。所以我认为这会更快:

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
于 2013-07-23T13:41:01.367 回答