【问题标题】:CASE statement divided by another CASE statement gives value 0CASE 语句除以另一个 CASE 语句给出值 0
【发布时间】:2016-06-28 22:10:15
【问题描述】:

我正在根据每年的年份和月份计算比率。两个 CASE 语句都带来了正确的值,需要进行划分。但由于某种原因,我得到了 0 或 -100

;WITH cte_yoyComparison
AS
        (
SELECT  Year(EffectiveDate) AS EffectiveYear,
        Month(EffectiveDate) AS EffectiveMonth,
        SUM(Premium) as Premium 
FROM    Test_Plaza_ProductionReport 
WHERE YEAR(EffectiveDate) <> 2017
GROUP BY      Year(EffectiveDate),
                Month(EffectiveDate)            
            )
SELECT *, b.YearNum,b.MonthNum,

            ((case when b.YearNum=2016 and b.MonthNum=1 THEN Premium   end ))   /(case when b.YearNum = 2015 and b.MonthNum = 1 THEN Premium end)  as Ratio,
            ((((case when b.YearNum=2015 and b.MonthNum=1 THEN Premium   else 0 end))   /NULLIF((case when b.YearNum = 2016 and b.MonthNum = 1 THEN Premium   else 0 end),0))-1)*100 as Ratio1,
            case when b.YearNum=2015 and b.MonthNum=1 THEN Premium  else 0 end as CorrectValue,
            case when b.YearNum = 2016 and b.MonthNum = 1 THEN Premium else 0 end as CorrectValue1
 FROM tblCalendar b  
LEFT JOIN cte_yoyComparison a ON b.MonthNum=a.EffectiveMonth AND b.YearNum=a.EffectiveYear
WHERE b.YearNum<>2017
Order BY EffectiveYear desc,EffectiveMonth

【问题讨论】:

  • Premium 列的数据类型是什么?
  • Int 除以较大的 int 将产生零。将分子或分母转换为带小数的东西
  • 我尝试将分子转换为 FLOAT,结果相同

标签: sql tsql case


【解决方案1】:

您似乎想要比较 2 行而不是两列,但实际上是在比较 1 列和 2 个值。

((case when b.YearNum=2016 and b.MonthNum=1 THEN Premium   end ))   /(case when b.YearNum = 2015 and b.MonthNum = 1 THEN Premium end)  as Ratio,

将始终计算为 NULL / PremiumPremium / Null,因为 b.YearNum 不能是同一行中的 2 个值

((((case when b.YearNum=2015 and b.MonthNum=1 THEN Premium   else 0 end))   /NULLIF((case when b.YearNum = 2016 and b.MonthNum = 1 THEN Premium   else 0 end),0))-1)*100 as Ratio1,

将始终评估为 0 / (Premium -1) * 100Premium / (-1 * 100)

您不是在比较行,而是在比较列,在这种情况下,同一列的值与 2 个不同的值。

您的意思是通过查看表a 而不是b 来评估分区的一侧?

只知道我可以在您的查询中看到什么,让您的 cte 保持原样,只需将您的查询从它更改为如下所示。请注意,我确实将您的 tblCalendar 从 a 更改为 c,因为对我来说日历以 c 开头。

SELECT *,
    ISNULL(a.Premium,0) / ISNULL(b.Premium,1) AS Ratio
FROM tblCalendar c  
    LEFT JOIN cte_yoyComparison a
    ON c.MonthNum=a.EffectiveMonth
    AND c.YearNum=a.EffectiveYear
    LEFT JOIN cte_yoyComparison b
    ON c.MonthNum=b.EffectiveMonth
    AND c.YearNum - 1 = b.EffectiveYear
WHERE
    c.YearNum<>2017
ORDER BY
    c.YearNum DESC
    ,c.MonthNum

它的作用是自我加入您的 cte 的另一个副本,但比 s.yearnum 少 1 年因为您使用的是外部联接,它将包括所有年份等,因此如果没有匹配项,您需要处理空值。之后无需比较任何日期,因为您可以保证表 a 比表 b 新 1 年。

【讨论】:

  • b 表是日历表。即使没有数据,我也使用左连接来获取所有月份的数据。我添加了带有数据样本的图片
  • Oleg 您正在比较分子中的 b.value = 2016 和分母中的 b.value = b.2015。每行只有一个条件为真。这意味着您将始终获得至少一个案例陈述的 ELSE 部分。看看我告诉您的内容,它将评估您的描述所暗示的内容。您需要进行比较,甚至可能每年制定一个自我加入。
  • 谢谢。有没有与我的问题相关的示例?
  • 我刚刚更新了一些可能对你有用的东西。您需要比较 2 个不同的行,但作为列,具有不同条件的第二个连接本质上将为您提供正确的数据来计算。
  • 它有效。谢谢。我唯一需要三行,第一行将值 2016 与 2015 进行比较,这就是你所做的。但是,第二列是否有可能将 2015 年与 2014 年进行比较,第三列将 2014 年与 2013 年进行比较
【解决方案2】:

我已将* 1.00 添加到您的分子中,这基本上会导致十进制转换。

;WITH cte_yoyComparison
AS
        (
SELECT  Year(EffectiveDate) AS EffectiveYear,
        Month(EffectiveDate) AS EffectiveMonth,
        SUM(Premium) as Premium 
FROM    Test_Plaza_ProductionReport 
WHERE YEAR(EffectiveDate) <> 2017
GROUP BY      Year(EffectiveDate),
                Month(EffectiveDate)            
            )
SELECT *, b.YearNum,b.MonthNum,

            ((case when b.YearNum=2016 and b.MonthNum=1 THEN Premium * 1.00  end ))   
                     /(case when b.YearNum = 2015 and b.MonthNum = 1 THEN Premium * 1.00 end)  as Ratio,
            ((((case when b.YearNum=2015 and b.MonthNum=1 THEN Premium * 1.00  else 0 * 1.00 end))   
                      /NULLIF((case when b.YearNum = 2016 and b.MonthNum = 1 THEN Premium * 1.00  else 0 * 1.00 end),0))-1)*100 as Ratio1,
            case when b.YearNum=2015 and b.MonthNum=1 THEN Premium * 1.00  else 0 * 1.00 end as CorrectValue,
            case when b.YearNum = 2016 and b.MonthNum = 1 THEN Premium * 1.00 else 0 * 1.00 end as CorrectValue1
 FROM tblCalendar b  
LEFT JOIN cte_yoyComparison a ON b.MonthNum=a.EffectiveMonth AND b.YearNum=a.EffectiveYear
WHERE b.YearNum<>2017
Order BY EffectiveYear desc,EffectiveMonth

现在查看您的数据,很明显为什么您没有获得所需的结果集。你的加入条件说

  b.MonthNum=a.EffectiveMonth AND b.YearNum=a.EffectiveYear

匹配月份和年份,但在 case 语句中,您使用不同年份的 Numeratordenominator

您的 Case 语句与您的连接条件完全相反,因此 case 语句永远不会评估为 true,您将得到所有 NULLS。

【讨论】:

  • 现在我得到了 -100.0000000000
  • 如果您可以在您的问题中添加一些示例数据,这将有助于了解您哪里出错了。
  • (2016 年 1 月值 / 2015 年 1 月值)- 1
  • 应该很简单,我不知道自己做错了什么
  • 我添加了一张带有数据样本的图片
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-13
  • 1970-01-01
  • 2018-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多