【问题标题】:Divide By Zero Issue除以零问题
【发布时间】:2014-07-14 16:26:33
【问题描述】:

我目前遇到除以零的问题 - 我正在尝试实现 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

【问题讨论】:

  • 您的页数是多少?尝试注释掉 select 中的每一列,直到您确定是哪一列导致了错误。
  • 正如下面提到的@Bowlturner - 我认为选择底部的 Case 语句中的 PageCount 只是将 c.PageCount 信息减去我结合的所有 Case When 信息PageCount - CASE WHEN c.PageCount 为 NULL 或 c.PageCount=0 THEN 1 ELSE c.PageCount END

标签: sql sql-server ssms


【解决方案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

【讨论】:

  • 那里的合并是为了确保什么? (我只是好奇,因为我以前没有使用过它,但根据微软的 T-SQL 信息 - 返回具有最高数据类型优先级的表达式的数据类型。如果所有表达式都不可为空,则结果类型为不可空)
  • 尝试在所有除法公式上添加 NULLIF(如果您查看最后一个 Case 语句,则有一些),它给了我以下错误:将 int 转换为数据类型数字的算术溢出错误。跨度>
  • coalesce 替换一个备用返回值,以防计算无意义(即 datediff = 0 或日期为空等)。基本思想是将业务逻辑与显示逻辑分离。
  • Arithmetic overflow error converting int to data type numeric. 好吧,numeric(5,2) 是 {-999.99 .. 999.99}。您的 PageCount >= 1000 吗?
  • 是的,我确实有几个 PageCount >= 1000 的 Pagcounts
【解决方案2】:

我认为您的问题出在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。

【讨论】:

  • 保留原始查询中的所有内容并仅添加您的建议仍然会给我“遇到除以零错误”
【解决方案3】:

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

我知道的所有 sql,您不能在选择的其他位置使用别名列。通过将 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]

【讨论】:

  • 是的 - 我想可能是这样 - 将整个 Case When c.PageCount... 更改为 [PageCount2] 并将所有后续 PageCounts 更改为 PageCount2 会给我一个错误。所以是的,我相信从技术上讲,它是用 cPageCount 减去所有案例内容。
  • 因此,您只需将 PageCount 案例放在 select 子句中有 [PageCount] 的任何地方。
  • 对,但我相信 Pagecount 给了我一个 0 导致除以 0 - 所以我试图弄清楚如何使用 Pagecount 使整个 Case 语句适用于使用 Pagecount 划分的 Case 语句.
  • 保持一切不变 - 只是添加你的建议会给我以下错误:“算术溢出错误转换为数据类型数字” - 这是我在 @Anon 的查询中遇到的类似错误
猜你喜欢
  • 1970-01-01
  • 2019-01-10
  • 2018-03-22
  • 2021-03-15
  • 1970-01-01
  • 1970-01-01
  • 2011-10-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多