【问题标题】:Stored Procedure to display different COUNT in SELECT clause在 SELECT 子句中显示不同 COUNT 的存储过程
【发布时间】:2012-01-20 05:02:26
【问题描述】:

我已经尝试了好几个小时来解决问题,但我还没有想出合适的解决方案。

我在 SQL Server 中有一个名为 EmailTasks 的表:

 Id  | HasFailed | CreateDate
 19  |   1       |  10/11/2011
 29  |   0       |  09/11/2011
 15  |   1       |  14/12/2011

我想构建一个接受两个参数的存储过程:@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  

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

【问题讨论】:

    标签: asp.net .net sql sql-server stored-procedures


    【解决方案1】:

    你总是可以这样做:

    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
    

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

    如果 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 
    
    • 强制转换是必要的,因为 sum 运算符在 bit 字段上无效,正如 Martin Smith 所指出的那样

    【讨论】:

    • "(a bit field)" - 或作为标志的整数字段。
    • @MarkBannister:我的意思是,如果有某种机制(不管它是什么)可以保证某处不会有松散的 2 :)
    • 如果是bit,则需要转换为int 才能聚合它。
    • 看起来缺少一些 () 以正确编译存储的过程。
    • 我不认为最后一个解决方案不太清楚,这就是我想要的。但是有一点优化:COUNT(*) - sum(cast(HasFailed as int)) AS Success - 这通过允许优化器重新使用其他两个字段的值来避免新的计算聚合。
    【解决方案2】:

    试试这个 SQL

    select count(*) as TotalEmails, sum(HasFailed) as Failed, sum(1-HasFailed) as Success
     from EmailTasks where CreateDate between @beginDate and @endDate
    

    【讨论】:

    • 很好,除了 Martin Smith 在您回答前 31 分钟发表的评论 - 如果不将 BIT 转换为 INT 或其他类型,您就无法 SUM() 。
    猜你喜欢
    • 1970-01-01
    • 2014-01-07
    • 1970-01-01
    • 2011-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多