【问题标题】:Why do I have different result by using CASE statement?为什么使用 CASE 语句会得到不同的结果?
【发布时间】:2016-06-15 00:32:05
【问题描述】:

我正在使用 CASE 语句来计算溢价,如果我只使用 SELECT SUM 语句,结果会很差。为什么会这样?

select 
        SUM(CASE WHEN Premium > 0 and Premium <= 5000 AND Year(EffectiveDate)=2016 AND PolicyType = 'New Business' THEN Premium ELSE 0 END) as '0-5K_WP',
        SUM(CASE WHEN Premium > 5000 and Premium <=10000 AND Year(EffectiveDate)=2016 AND PolicyType = 'New Business' THEN Premium ELSE 0 END) AS '5K-10K_WP',
        SUM(CASE WHEN Premium > 10000 and Premium <= 25000 AND Year(EffectiveDate)=2016 AND PolicyType = 'New Business'   THEN Premium ELSE 0 END) AS '10K-25K_WP',
        SUM(CASE WHEN Premium > 25000 and Premium <=50000 AND Year(EffectiveDate)=2016 AND PolicyType = 'New Business'  THEN Premium ELSE 0 END) AS '25K-50K_WP',
        SUM(CASE WHEN Premium > 50000 AND Year(EffectiveDate)=2016 AND PolicyType = 'New Business'  THEN Premium ELSE 0 END) AS '>50K_WP'
FROM    Test_Plaza_ProductionReport 

union all 
select 
        SUM(CASE WHEN Premium > 0 and Premium <= 5000 AND Year(EffectiveDate)=2016 AND PolicyType = 'Renewal' THEN Premium ELSE 0 END) as '0-5K_WP',
        SUM(CASE WHEN Premium > 5000 and Premium <=10000 AND Year(EffectiveDate)=2016 AND PolicyType = 'Renewal' THEN Premium ELSE 0 END) AS '5K-10K_WP',
        SUM(CASE WHEN Premium > 10000 and Premium <= 25000 AND Year(EffectiveDate)=2016 AND PolicyType = 'Renewal' THEN Premium ELSE 0 END) AS '10K-25K_WP',
        SUM(CASE WHEN Premium > 25000 and Premium <=50000 AND Year(EffectiveDate)=2016 AND PolicyType = 'Renewal' THEN Premium ELSE 0 END) AS '25K-50K_WP',
        SUM(CASE WHEN Premium > 50000 AND Year(EffectiveDate)=2016 AND PolicyType = 'Renewal' THEN Premium ELSE 0 END) AS '>50K_WP'
FROM    Test_Plaza_ProductionReport 

union all 
select 

        SUM(CASE WHEN Premium >0 and Premium <= 5000 AND Year(EffectiveDate)=2016 AND  PolicyType = 'Rewrite' THEN Premium ELSE 0 END) as '0-5K_WP',
        SUM(CASE WHEN Premium > 5000 and Premium <=10000 AND Year(EffectiveDate)=2016 AND  PolicyType = 'Rewrite' THEN Premium ELSE 0 END) AS '5K-10K_WP',
        SUM(CASE WHEN Premium > 10000 and Premium <= 25000 AND Year(EffectiveDate)=2016 AND  PolicyType = 'Rewrite' THEN Premium ELSE 0 END) AS '10K-25K_WP',
        SUM(CASE WHEN Premium > 25000 and Premium <=50000 AND Year(EffectiveDate)=2016 AND  PolicyType = 'Rewrite' THEN Premium ELSE 0 END) AS '25K-50K_WP',
        SUM(CASE WHEN Premium > 50000 AND Year(EffectiveDate)=2016 AND  PolicyType = 'Rewrite' THEN Premium ELSE 0 END) AS '>50K_WP'
FROM    Test_Plaza_ProductionReport 

总和将是 13,286,473 但现在如果我使用这个:

select sum(premium) 
from Test_Plaza_ProductionReport  
where PolicyType in ('New Business','Renewal','Rewrite') 
and Year(EffectiveDate)=2016

现在总和是 11,993,445 减200万!!这怎么可能?

【问题讨论】:

  • 在标准中看不到任何重叠,但您在基础数据中有负值
  • 约翰,是的,我确实有负值。我也必须考虑到它们。
  • 那么我应该使用什么来考虑它们?
  • 为负值添加一个层。我也会考虑 t tier table 让生活更轻松
  • 旁白:由于 PolicyType 和 year 逻辑并且对于单个 case 中的所有表达式都是通用的 select 您可以将其从表达式中删除并添加 where 子句: select ... from Test_Plaza_Production where PolicyType = 'New Business' and Year( EffectiveDate ) = 2016 union ....

标签: sql-server tsql reporting-services


【解决方案1】:

您的保单记录中似乎有一些保费为负数的记录。向简短查询添加条件以拒绝此类负溢价记录应该使您的数字匹配。

如果您想考虑负溢价,请为它们添加一个额外的“桶”,即

select 
        SUM(CASE WHEN Premium < 0 AND Year(EffectiveDate)=2016 AND PolicyType = 'Renewal' THEN Premium ELSE 0 END) as 'Negative_WP',
        SUM(CASE WHEN Premium > 0 and Premium <= 5000 AND Year(EffectiveDate)=2016 AND PolicyType = 'Renewal' THEN Premium ELSE 0 END) as '0-5K_WP',
        SUM(CASE WHEN Premium > 5000 and Premium <=10000 AND Year(EffectiveDate)=2016 AND PolicyType = 'Renewal' THEN Premium ELSE 0 END) AS '5K-10K_WP',
        SUM(CASE WHEN Premium > 10000 and Premium <= 25000 AND Year(EffectiveDate)=2016 AND PolicyType = 'Renewal' THEN Premium ELSE 0 END) AS '10K-25K_WP',
        SUM(CASE WHEN Premium > 25000 and Premium <=50000 AND Year(EffectiveDate)=2016 AND PolicyType = 'Renewal' THEN Premium ELSE 0 END) AS '25K-50K_WP',
        SUM(CASE WHEN Premium > 50000 AND Year(EffectiveDate)=2016 AND PolicyType = 'Renewal' THEN Premium ELSE 0 END) AS '>50K_WP'
FROM    Test_Plaza_ProductionReport 

【讨论】:

  • 哦,你是对的。我确实有负保费,但我也必须考虑到它们。
  • 是的!!!!非常感谢你!我只是想知道,如果我不将它放入单独的“桶”中,为什么它不会给我相同的结果?说 SUM(CASE WHEN Premium
  • @Oleg Premium &lt; 0 and Premium &lt;= 5000 是多余的:如果某个值小于零,那么它肯定也小于 5000。不过,使用 Premium &lt;= 5000 会起作用。
  • 谢谢哥们。很抱歉提出愚蠢的问题。我想我该回家了
【解决方案2】:

您很可能有一个负数,但您的 CASE 语句仅适用于正数。

运行相同的查询,最后一个 sum 加上额外的 where 谓词,用于检查 premium

【讨论】:

    【解决方案3】:

    供您考虑,正如我所提到的,这是使用层表的一种方法。想象一下,定义的多个层支持大量请求和报告

    假设您有一个这样的表 Tiers

    Tier_Grp      Tier_Title    Tier_R1         Tier_R2
    Policy Size   < 0           -999999999.00   0.00
    Policy Size   0 - 5K         0.00           5000.00
    Policy Size   5K - 10K       5000.00        10000.00
    Policy Size   10K - 25K      10000.00       25000.00
    Policy Size   25K - 50K      25000.00       50000.00
    Policy Size   > 50K          50000.00       999999999.00
    Policy Size   Total          -999999999.00  999999999.00
    

    然后通过 1 个简单的查询,您可以获得所有数据、计数、总和、平均值

    Select PolicyType
          ,B.Tier_Title
          ,NbrOfPolicies = count(*)
          ,Premium       = sum(Policy)
    FROM   Test_Plaza_ProductionReport  A
    Join   Tiers on (B.Tier_Grp='Policy Size' and Premium between B.Tier_R1 and B.Tier_R2 and Premium<B.Tier_R2)
    Where  Year(EffectiveDate)=2016
    Group  By PolicyType
          ,B.Tier_Title  
    Order  By PolicyType
          ,B.Tier_R2
    

    【讨论】:

      猜你喜欢
      • 2015-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多