除以零问题

时间:2014-07-14 16:26:33

标签: sql sql-server ssms

我目前遇到的问题是除以零 - 我试图实施CASE只是将划分的数字标记为" 1"但是,我仍然得到错误 - 我猜我在这里遗漏了什么?只是不确定是什么......

SELECT
    CASE WHEN c.PageCount IS NULL OR c.PageCount=0 THEN 1 ELSE c.PageCount END as [PageCount], 

    cast(c.PageCount / CASE WHEN DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) IS NULL OR DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) = 0 THEN 1 ELSE DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate)END as decimal(5,2)) as PagesPerMinute,

    CASE
       WHEN DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) >= 30 AND CAST(DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) AS FLOAT)/CAST([PageCount] AS FLOAT) >= 1 THEN 
             CASE WHEN CAST([PageCount] AS FLOAT) * 0.5 /*Half minute*/ > 45 /*minutes*/ THEN 45 ELSE CAST([PageCount] AS FLOAT) * 0.5 /*Half minute*/ END 
       WHEN DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) >= 60 AND CAST(DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) AS FLOAT)/CAST([PageCount] AS FLOAT) < 1 /* 1 minute/page */ THEN 60
       ELSE
         DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate)
    END    [MinutesPaid]


FROM 
    tbl_Charts c
    left outer join (select cd.ChartId, count(*) as CodesFound from tbl_ChartCodes cd group by cd.ChartId) cd on cd.ChartId = c.ChartId,
    tbl_WFChartEvents ev, 
    tbl_Users u,
    (select evar.ChartId, evar.ActionUserId, ar.ResultDescription, evar.ActionRemark, evar.ActionDate
    from tbl_WFChartEventActions evar, tbl_WFChartEventActionResults ar 
    where evar.EventId = 201 
    and evar.ActionResultId = ar.ResultID and evar.EventId = ar.EventID 
    and evar.ActionTypeId = ar.ActionTypeID
    and evar.EventId = 201) arr 

WHERE 
c.ChartId = ev.ChartId
and ev.EventId = 201
and ev.EventCreateUserId = u.UserId
and arr.ActionUserId = u.UserId
and arr.ChartId = c.ChartId

order by ev.EventCreateDate

3 个答案:

答案 0 :(得分:1)

为了便于分割公式的可读性/可维护性,请使用NULLIF(x,0)包装每个除数。

这比使用case语句检查零并确保除数与case谓词相同更容易。在任何地方,您都会看到/ [...],将其设为/ NULLIF( [...] ,0)

而不是:

cast(
  c.PageCount / CASE
                  WHEN (DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) IS NULL 
                     OR DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) = 0
                  )
                  THEN 1
                  ELSE DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate)
                END
  as decimal(5,2)
) as PagesPerMinute,

这样做:

cast(
  coalesce(
    c.PageCount / NULLIF(DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate), 0)
   ,c.PageCount --Return this value if preceding is null or div_by_zero
  )
  as as decimal(5,2)
) as PagesPerMinute

答案 1 :(得分:0)

好的,第三次魅力?我以为我发现了两次问题,但我想我知道现在发生了什么。

我知道所有的sql,你不能在select中使用别名列。通过将c.PageCount别名化为[PageCount],我相信您仍在使用原始的c.PageCount而不使用表别名。要测试它,只需将[PageCount]更改为[PageCount2]。我怀疑你会收到一个错误,它无法识别列名。

这只会“显示”才能生效,因为您重复使用了结果中已有的唯一列名称。

我的意思是采用这种情况并用它替换[PageCount]。

CASE WHEN c.PageCount IS NULL OR c.PageCount=0 THEN 1 ELSE c.PageCount END
像这样

CASE
   WHEN DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) >= 30 AND CAST(DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) AS FLOAT)/CAST(CASE WHEN c.PageCount IS NULL OR c.PageCount=0 THEN 1 ELSE c.PageCount END AS FLOAT) >= 1 THEN 
         CASE WHEN CAST([PageCount] AS FLOAT) * 0.5 /*Half minute*/ > 45 /*minutes*/ THEN 45 ELSE CAST([PageCount] AS FLOAT) * 0.5 /*Half minute*/ END 
   WHEN DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) >= 60 AND CAST(DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) AS FLOAT)/CAST(CASE WHEN c.PageCount IS NULL OR c.PageCount=0 THEN 1 ELSE c.PageCount END AS FLOAT) < 1 /* 1 minute/page */ THEN 60
   ELSE
     DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate)
END    [MinutesPaid]

答案 2 :(得分:0)

我认为您的问题出在case声明中:

CASE WHEN DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) >= 30 AND
          CAST(DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) AS FLOAT)/CAST([PageCount] AS FLOAT) >= 1
     THEN (CASE WHEN CAST([PageCount] AS FLOAT) * 0.5 /*Half minute*/ > 45 /*minutes*/
                THEN 45 ELSE CAST([PageCount] AS FLOAT) * 0.5 /*Half minute*/
           END)
     WHEN DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) >= 60 AND CAST(DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) AS FLOAT)/CAST([PageCount] AS FLOAT) < 1 /* 1 minute/page */
     THEN 60
     ELSE DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate)
END AS [MinutesPaid]

第一个when语句有一个除法。只需将其改为:

CASE WHEN DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) >= 30 AND
          CAST([PageCount] AS FLOAT) > 0 AND
          CAST(DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) AS FLOAT) >= CAST([PageCount] AS FLOAT)
     THEN (CASE WHEN CAST([PageCount] AS FLOAT) * 0.5 /*Half minute*/ > 45 /*minutes*/
                THEN 45 ELSE CAST([PageCount] AS FLOAT) * 0.5 /*Half minute*/
           END)
     WHEN DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) >= 60 AND CAST(DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate) AS FLOAT)/CAST([PageCount] AS FLOAT) < 1 /* 1 minute/page */
     THEN 60
     ELSE DATEDIFF(mi, ev.EventCreateDate, ev.EventCompletionDate)
END AS [MinutesPaid]

我通过简单的比较删除了除法,并且保证该值不为0.