存储过程在SELECT子句中显示不同的COUNT

ori*_*hen 3 .net sql sql-server asp.net stored-procedures

我已经花了好几个小时才想出办法,但我还没有找到合适的解决方案.

我有一个EmailTasks在SQL Server 中调用的表:

 Id  | HasFailed | CreateDate
 19  |   1       |  10/11/2011
 29  |   0       |  09/11/2011
 15  |   1       |  14/12/2011
Run Code Online (Sandbox Code Playgroud)

我想构建一个接受两个参数的存储过程:@beginDate,@endDate.

它从表中选择相关记录EmailTasks(即CreateDate@beginDate和之间 @endDate)并返回包含3列的下表:

  1. TotalEmails:电子邮件总数,
  2. Failed:失败的电子邮件数(hasFailed = 1),
  3. Suceess:成功的电子邮件数(hasFailed = 0).

例如:sp_GetEmailTemplateStatistics('08/11/2011', '11/11/2011')将返回:

TotalEmails | Failed | Suceess
     2      |  1     |  1  
Run Code Online (Sandbox Code Playgroud)

请注意:Id=15由于CreateDate(14/12/2011)大于参数,因此记录不计算在内@endDate.

SWe*_*eko 9

你总是可以这样做:

select 
  (select count(*) from EmailTasks 
    where CreateDate between @beginDate and @endDate)
    as TotalEmails,
  (select count(*) from EmailTasks 
    where CreateDate between @beginDate and @endDate 
      and HasFailed = 1)
    as Failed,
  (select count(*) from EmailTasks 
    where CreateDate between @beginDate and @endDate 
      and HasFailed = 0)
    as Suceess
Run Code Online (Sandbox Code Playgroud)

这将返回正确的值,但会对表执行三次,并且它的条件重复三次,因此如果修改了逻辑,则可能会出现粘贴错误.

如果HasFailed将始终为0或1(一个bit字段),您可以做到更聪明但不太清楚的解决方案:

  select 
    count(*) as TotalEmails, 
    sum(cast(HasFailed as int)) as Failed, 
    sum(1-cast(HasFailed as int)) as Suceess
  from EmailTasks 
    where CreateDate between @beginDate and @endDate 
Run Code Online (Sandbox Code Playgroud)
  • 如马丁史密斯指出的那样,施法是必要的,因为sum操作员在bit田地上是无效的

  • 如果是'bit`,你需要转换为`int`来聚合它. (2认同)