SQL查询 – 多列的SUM(CASE WHEN x THEN 1 ELSE 0)

我想看看下面的查询是否有更好的方法.我要做的是创建一个摘要报告,按日期编制统计数据.
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

这只是查询一个示例(在报告中使用),因为有许多其他列,而其他统计信息的逻辑则更复杂.是否有更优雅的方法获取此类信息/撰写此类报告?

解决方法

我会通过以下方式更改查询

>在子查询中进行聚合.这可以利用有关该表的更多信息来优化组.
>组合第二个和第三个子查询.它们聚合在同一列上.这需要使用左外连接以确保所有数据都可用.
>通过使用count(< fieldname>),您可以消除比较为null.这对于第二个和第三个计算值很重要.
>要组合第二个和第三个查询,需要计算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,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;

以下使用完全外连接执行类似操作:

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;

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 &#39;EastRiver&#39; 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...