【问题标题】:Divide by 0 Error Inside Windows FunctionWindows 函数内除以 0 错误
【发布时间】:2020-02-10 18:41:33
【问题描述】:

我正在尝试使用 Windows 函数计算已结索赔的百分比除以每月总索赔。但是有些月份的索赔总数为零,这会导致Divide by zero error encountered 消息。

我尝试编写 CASE 语句来处理索赔总数为零的情况,将百分比设置为零,但到目前为止我还没有运气。

下面是我所期待的截图:

下面的 TSQL 是我在处理除以零消息时出错的尝试:我在分隔符底部添加了一个 NULLIF,并尝试在底部分隔符为零时在 CASE 语句中设置值 = 0 - 两者都导致相同的错误。有关如何解决此错误的任何建议?

CREATE TABLE #ClaimCounts
(
Year INT,
ClaimStatus VARCHAR (50),
LossMonth DATE,
ClaimMonth DATE,
ClaimCount INT
);

INSERT INTO #ClaimCounts
(
Year,
ClaimStatus,
LossMonth,
ClaimMonth,
ClaimCount
)
VALUES
(2008, 'Closed', '20080630', '20080131', 0),
(2008, 'Total', '20080630', '20080131', 0),
(2008, 'Closed', '20080630', '20080229', 0),
(2008, 'Total', '20080630', '20080229', 0),
(2008, 'Closed', '20080630', '20080331', 0),
(2008, 'Total', '20080630', '20080331', 0),
(2008, 'Closed', '20080630', '20080430', 0),
(2008, 'Total', '20080630', '20080430', 0),
(2008, 'Closed', '20080630', '20080531', 0),
(2008, 'Total', '20080630', '20080531', 0),
(2008, 'Closed', '20080630', '20080630', 0),
(2008, 'Total', '20080630', '20080630', 6),
(2008, 'Closed', '20080630', '20090731', 2),
(2008, 'Total', '20080630', '20090731', 5),
(2008, 'Closed', '20080630', '20080831', 1),
(2008, 'Total', '20080630', '20080831', 1),
(2008, 'Closed', '200806308', '20080930', 3),
(2008, 'Total', '20080630', '20080930', 3),
(2008, 'Closed', '20080630', '20081031', 2),
(2008, 'Total', '20080630', '20081031', 3),
(2008, 'Closed', '200806308', '20081130', 0),
(2008, 'Total', '20080630', '20081130', 0);

SELECT Year,
   ClaimStatus,
   LossMonth,
   ClaimMonth,
   ClaimCount,
   SUM ( CASE WHEN ClaimStatus = 'Closed' THEN ISNULL ( ClaimCount, 0 ) * 1.0 ELSE 0 END ) OVER (PARTITION BY Year, ClaimMonth) / 
   SUM ( CASE WHEN ClaimStatus = 'Total' THEN ClaimCount * 1.0 ELSE 0 END ) OVER (PARTITION BY Year, ClaimMonth) AS PercentageClosedClaims1 ,

   SUM ( CASE WHEN ClaimStatus = 'Closed' THEN ISNULL ( ClaimCount, 0 ) * 1.0 ELSE 0 END ) OVER (PARTITION BY Year, ClaimMonth) / 
   SUM ( CASE WHEN ClaimStatus = 'Total' THEN NULLIF(ClaimCount, 0) * 1.0 ELSE 0 END ) OVER (PARTITION BY Year, ClaimMonth) AS PercentageClosedClaims2 ,

   CASE WHEN ClaimStatus = 'Total' AND ClaimCount = 0 THEN 0
       ELSE SUM ( CASE WHEN ClaimStatus = 'Closed' THEN ISNULL ( ClaimCount, 0 ) * 1.0 ELSE 0 END ) OVER (PARTITION BY Year, ClaimMonth) / 
            SUM ( CASE WHEN ClaimStatus = 'Total' THEN ISNULL ( ClaimCount, 0 ) * 1.0 ELSE 0 END ) OVER (PARTITION BY Year, ClaimMonth)
   END AS PercentageClosedClaims3
FROM #ClaimCounts;

DROP TABLE IF EXISTS #ClaimCounts;

【问题讨论】:

  • IsNull( YourNumerator / NullIf(YourDenominator,0) , 0 )
  • DDL 和 DML 很棒,但请尽量避免特定语言的日期。对于世界上大部分地区来说,一年没有 30 个月。 :) ISO 格式 yyyyMMddyyyy-MM-ddThh:mm:ss.nnnnnnn 总是首选,因为这样人们就不需要更改他们的语言设置或修改您的数据,因此它是可消耗的。谢谢。
  • 感谢@Larnu - 我已经更新了 TSQL。
  • @JohnCappelletti - 我不确定如何将您的答案应用到我的代码中。
  • @MISNole 请参阅下面的答案

标签: tsql sql-server-2016


【解决方案1】:

这是一个可行的选项。 IsNull() 是可选的。我个人不介意NULL 值。

SELECT Year
      ,ClaimStatus
      ,LossMonth
      ,ClaimMonth
      ,ClaimCount
      ,PercentageClosedClaims1 = IsNull(SUM ( CASE WHEN ClaimStatus = 'Closed' THEN ISNULL ( ClaimCount, 0 ) * 1.0 ELSE 0 END ) OVER (PARTITION BY Year, ClaimMonth) 
                                        / nullif(SUM ( CASE WHEN ClaimStatus = 'Total' THEN ClaimCount * 1.0 ELSE 0 END ) OVER (PARTITION BY Year, ClaimMonth),0) 
                                        ,0)
      ,PercentageClosedClaims2 = IsNull(SUM ( CASE WHEN ClaimStatus = 'Closed' THEN ISNULL ( ClaimCount, 0 ) * 1.0 ELSE 0 END ) OVER (PARTITION BY Year, ClaimMonth) 
                                        / nullif(SUM ( CASE WHEN ClaimStatus = 'Total' THEN NULLIF(ClaimCount, 0) * 1.0 ELSE 0 END ) OVER (PARTITION BY Year, ClaimMonth),0) 
                                        ,0)
      ,PercentageClosedClaims3 = IsNull(SUM ( CASE WHEN ClaimStatus = 'Closed' THEN ISNULL ( ClaimCount, 0 ) * 1.0 ELSE 0 END ) OVER (PARTITION BY Year, ClaimMonth) 
                                        / nullif(SUM ( CASE WHEN ClaimStatus = 'Total' THEN ISNULL ( ClaimCount, 0 ) * 1.0 ELSE 0 END ) OVER (PARTITION BY Year, ClaimMonth),0)
                                        ,0)

FROM #ClaimCounts;

【讨论】:

  • 感谢约翰的回答!为了让我想起分子和分母这两个术语——我完全忘记了这些术语。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-02
  • 2012-03-25
相关资源
最近更新 更多