【问题标题】:Case statement and divide by zero error案例陈述和除以零错误
【发布时间】:2013-05-21 16:05:17
【问题描述】:

我得到一个除以零的错误,我不知道如何处理它。使用 sql server 数据库。

脚本:

SELECT  Race ,
        [2012] = MAX(CASE WHEN a.[Year] = 2012 THEN [Count]
                     END) ,
        [% Inc Dec] = ( MAX(CAST(CASE WHEN a.[Year] IS NULL THEN ''
                        ELSE a.[Year] = 2011 THEN [Count]
                                 END AS FLOAT))
                        - MAX(CAST(CASE WHEN a.[Year] IS NULL THEN ''
                        ELSE a.[Year] = 2012 THEN [Count]
                                   END AS FLOAT)) )
        / MAX(CAST(CASE WHEN a.[Year] IS NULL THEN ''
                        ELSE a.[Year] = 2012 THEN [Count]
                   END AS FLOAT)) ,
        [2011] = MAX(CASE WHEN a.[Year] = 2011 THEN [Count]
                     END) ,
        [% Inc Dec] = ( MAX(CAST(CASE WHEN a.[Year] = 2010 THEN [Count]
                                 END AS FLOAT))
                        - MAX(CAST(CASE WHEN a.[Year] = 2011 THEN [Count]
                                   END AS FLOAT)) )
        / MAX(CAST(CASE WHEN a.[Year] = 2010 THEN [Count]
                   END AS FLOAT)) ,
        [2010] = MAX(CASE WHEN a.[Year] = 2010 THEN [Count]
                     END) ,
        [2009] = MAX(CASE WHEN a.[Year] = 2009 THEN [Count]
                     END) ,
        [% Inc Dec] = ( MAX(CAST(CASE WHEN a.[Year] = 2008 THEN [Count]
                                 END AS FLOAT))
                        - MAX(CAST(CASE WHEN a.[Year] = 2009 THEN [Count]
                                   END AS FLOAT)) )
        / MAX(CAST(CASE WHEN a.[Year] = 2009 THEN [Count]
                   END AS FLOAT)) 
FROM    @Data

我试图更改前两个 case 语句,但它不正确。任何帮助或推动正确的方向将不胜感激。

【问题讨论】:

  • CASE WHEN Denominator = 0 THEN 0
  • expression / NULLIF(Denominator,0) 将返回 NULL 而不是错误。
  • @data 中的数据是什么样的?只是种族、年份和计数列?还是 a.[year] 来自@data 之外的来源?我认为自联接可能是从 2 个不同行中减去值的更好方法,其中一行是第二年。

标签: sql sql-server case


【解决方案1】:

我假设a 是@Data 的别名,或者它与race 和[count] 在同一个表/源中,所以您的数据如下所示:

race    YEAR      COUNT
w       2012      10
w       2011      50
w       2010      100
b       2010      200
b       2009      75

并且您预计数据会随着时间的推移而减少。在减法和除法之前,我会使用自联接来确保高年和低年都有值,如下所示:

SELECT
 race, 
 y1.[YEAR] AS yr1, y1.[COUNT] AS cnt1, 
 y2.[YEAR] AS yr2, y2.[COUNT] AS cnt2, 
 (cnt2 - cnt1) / cnt1 AS pct_inc_dec
FROM 
 @DATA y1 INNER JOIN 
 @DATA y2 ON 
 y1.race = y2.race AND
 y1.YEAR = y2.YEAR - 1  -- y1 is the later year

那么你根本不用担心被零除,除非计数本身为零。


然后,使用您提供的代码,自联接将在交叉应用的枢轴之后应用于存储的表。您可以结合您上一年的标准,这样它就不必放在自己的表格中:

DECLARE @DATA TABLE
    (
      [YEAR] INT ,
      [COUNT] INT ,
      race VARCHAR(50)  
    )

INSERT  INTO @DATA
SELECT  
    Race ,[COUNT], [YEAR]
FROM    
            (SELECT  
                dt.YEAR AS YEAR ,
                SUM(ISNULL(caucasian_enrollment, 0)) AS caucasian ,
                SUM(ISNULL(black_or_african_american_enrollment, 0)) AS Black ,
                SUM(ISNULL(asian_enrollment,0)) AS Asian ,
                SUM(ISNULL(native_hawaiian_pacific_islander_enrollment, 0)) AS Native ,
                SUM(ISNULL(hispanic_enrollment, 0)) AS Hispanic ,
                SUM(ISNULL(american_indian_or_alaskan_ative_enrollment, 0)) AS [American Indian] ,
                SUM(ISNULL(multiracial_enrollment, 0)) AS multiracial ,
                SUM(ISNULL(unknown_ethnicity_enrollment, 0)) AS UNKNOWN ,
                SUM(ISNULL(male_enrollment, 0)) AS male,
                SUM(ISNULL(female_enrollment, 0)) AS female,
                SUM(ISNULL(Total_Enrollment, 0)) AS  [Total Enrollment]
            FROM    
                mart.dbo.f_s AS fes
                INNER JOIN TIME AS dt ON fes.time_key = dt.time_key
            WHERE   
                YEAR = '2012' 
            GROUP BY 
                dt.YEAR
        UNION ALL
            SELECT  
                dt.YEAR AS YEAR ,
                SUM(ISNULL(caucasian_enrollment, 0)) AS caucasian ,
                SUM(ISNULL(black_or_african_american_enrollment, 0)) AS Black ,
                SUM(ISNULL(asian_enrollment,0)) AS Asian ,
                SUM(ISNULL(native_hawaiian_pacific_islander_enrollment, 0)) AS Native,
                SUM(ISNULL(hispanic_enrollment, 0)) AS Hispanic,
                SUM(ISNULL(american_indian_or_alaskan_ative_enrollment, 0)) AS [American Indian] ,
                SUM(ISNULL(multiracial_enrollment, 0)) AS multiracial,
                SUM(ISNULL(unknown_ethnicity_enrollment, 0)) AS UNKNOWN,
                SUM(ISNULL(male_enrollment, 0)) AS male ,
                SUM(ISNULL(female_enrollment, 0)) AS female,
                SUM(ISNULL(Total_Enrollment, 0)) AS  [Total Enrollment]
            FROM    
                F5A_education_mart_IAK12.dbo.fact_enrollment_school AS fes
                INNER JOIN dim_time AS dt ON fes.time_key = dt.time_key
            WHERE   
                YEAR <= '2011' AND YEAR >= '2008'
            GROUP BY 
                dt.YEAR 
    ) d  CROSS APPLY 
    ( VALUES 
        ( 'Caucasian', caucasian, [YEAR])
        , ( 'Black', Black, [YEAR])
        , ( 'Asian', Asian, [YEAR]) 
        , ('Native', Native, [YEAR]) 
        , ('Hispanic', Hispanic, [YEAR]) 
        , ('American Indian', [American Indian], [YEAR]) 
        , ('Multiracial', multiracial, [YEAR])
        , ('Unkown', UNKNOWN, [YEAR]) 
        , ('Male', male, [YEAR]) 
        , ('Female', female, [YEAR]) 
        , ('Total Enrollment', [Total Enrollment], [YEAR]) 
        ) a ( Race, [COUNT], [YEAR] ) 
 GROUP BY 
    Race    

SELECT
    race, 
    y1.[YEAR] AS yr1, y1.[COUNT] AS cnt1, 
    y2.[YEAR] AS yr2, y2.[COUNT] AS cnt2, 
    (cnt2 - cnt1) / cnt1 AS pct_inc_dec
FROM 
    @DATA y1 INNER JOIN 
    @DATA y2 ON 
    y1.race = y2.race AND
    y1.YEAR = y2.YEAR - 1  -- y1 is the later year

【讨论】:

    【解决方案2】:

    感谢 T I 和 Martin 的快速响应。最初我没有发布完整的脚本,因为我只是对我的案例陈述有问题,我无法让 ISNULL 工作。以下是完整的结果和答案:

        DECLARE @Data TABLE
        (
          [Year] INT ,
          caucasian INT ,
          Black INT ,
          Asian INT ,
          Native INT ,
          Hispanic INT ,
          [American Indian] INT ,
          Multiracial INT ,
          UNKNOWN INT ,
          Male INT ,
          Female INT , 
          [Total Enrollment] INT 
        )
    
    INSERT  INTO @Data
            SELECT  dt.year AS Year ,
                    SUM(ISNULL(caucasian_enrollment, 0)) ,
                    SUM(ISNULL(black_or_african_american_enrollment, 0)) ,
                    SUM(ISNULL(asian_enrollment,0)) ,
                    SUM(ISNULL(native_hawaiian_pacific_islander_enrollment, 0)) ,
                    SUM(ISNULL(hispanic_enrollment, 0)) ,
                    SUM(ISNULL(american_indian_or_alaskan_ative_enrollment, 0)) ,
                    SUM(ISNULL(multiracial_enrollment, 0)) ,
                    SUM(ISNULL(unknown_ethnicity_enrollment, 0)) ,
                    SUM(ISNULL(male_enrollment, 0)) ,
                    SUM(ISNULL(female_enrollment, 0)) ,
                    SUM(ISNULL(Total_Enrollment, 0)) 
            FROM    mart.dbo.f_s AS fes
                    INNER JOIN time AS dt ON fes.time_key = dt.time_key
                    LEFT OUTER JOIN building AS db ON fes.building_key = db.building_key
            WHERE   year = '2012'
            GROUP BY dt.year
            UNION ALL
            SELECT  dt.year AS Year ,
                    SUM(ISNULL(caucasian_enrollment, 0)) ,
                    SUM(ISNULL(black_or_african_american_enrollment, 0)) ,
                    SUM(ISNULL(asian_enrollment,0)) ,
                    SUM(ISNULL(native_hawaiian_pacific_islander_enrollment, 0)) ,
                    SUM(ISNULL(hispanic_enrollment, 0)) ,
                    SUM(ISNULL(american_indian_or_alaskan_ative_enrollment, 0)) ,
                    SUM(ISNULL(multiracial_enrollment, 0)) ,
                    SUM(ISNULL(unknown_ethnicity_enrollment, 0)) ,
                    SUM(ISNULL(male_enrollment, 0)) ,
                    SUM(ISNULL(female_enrollment, 0)) ,
                    SUM(ISNULL(Total_Enrollment, 0)) 
            FROM    F5A_education_mart_IAK12.dbo.fact_enrollment_school AS fes
                    INNER JOIN dim_time AS dt ON fes.time_key = dt.time_key
                    LEFT OUTER JOIN dim_building AS db ON fes.building_key = db.building_key
            WHERE   year = '2011'
            GROUP BY dt.year
            UNION ALL
            SELECT  dt.year AS Year ,
                    SUM(ISNULL(caucasian_enrollment, 0)) ,
                    SUM(ISNULL(black_or_african_american_enrollment, 0)) ,
                    SUM(ISNULL(asian_enrollment,0)) ,
                    SUM(ISNULL(native_hawaiian_pacific_islander_enrollment, 0)) ,
                    SUM(ISNULL(hispanic_enrollment, 0)) ,
                    SUM(ISNULL(american_indian_or_alaskan_ative_enrollment, 0)) ,
                    SUM(ISNULL(multiracial_enrollment, 0)) ,
                    SUM(ISNULL(unknown_ethnicity_enrollment, 0)) ,
                    SUM(ISNULL(male_enrollment, 0)) ,
                    SUM(ISNULL(female_enrollment, 0)) ,
                    SUM(ISNULL(Total_Enrollment, 0)) 
            FROM    F5A_education_mart_IAK12.dbo.fact_enrollment_school AS fes
                    INNER JOIN dim_time AS dt ON fes.time_key = dt.time_key
                    LEFT OUTER JOIN dim_building AS db ON fes.building_key = db.building_key
            WHERE   year = '2010'
            GROUP BY dt.year
            UNION ALL
            SELECT  dt.year AS Year ,
                    SUM(ISNULL(caucasian_enrollment, 0)) ,
                    SUM(ISNULL(black_or_african_american_enrollment, 0)) ,
                    SUM(ISNULL(asian_enrollment,0)) ,
                    SUM(ISNULL(native_hawaiian_pacific_islander_enrollment, 0)) ,
                    SUM(ISNULL(hispanic_enrollment, 0)) ,
                    SUM(ISNULL(american_indian_or_alaskan_ative_enrollment, 0)) ,
                    SUM(ISNULL(multiracial_enrollment, 0)) ,
                    SUM(ISNULL(unknown_ethnicity_enrollment, 0)) ,
                    SUM(ISNULL(male_enrollment, 0)) ,
                    SUM(ISNULL(female_enrollment, 0)) ,
                    SUM(ISNULL(Total_Enrollment, 0)) 
            FROM    F5A_education_mart_IAK12.dbo.fact_enrollment_school AS fes
                    INNER JOIN dim_time AS dt ON fes.time_key = dt.time_key
                    LEFT OUTER JOIN dim_building AS db ON fes.building_key = db.building_key
            WHERE   year = '2009'
            GROUP BY dt.year
            UNION ALL
            SELECT  dt.year AS Year ,
                    SUM(ISNULL(caucasian_enrollment, 0)) ,
                    SUM(ISNULL(black_or_african_american_enrollment, 0)) ,
                    SUM(ISNULL(asian_enrollment,0)) ,
                    SUM(ISNULL(native_hawaiian_pacific_islander_enrollment, 0)) ,
                    SUM(ISNULL(hispanic_enrollment, 0)) ,
                    SUM(ISNULL(american_indian_or_alaskan_ative_enrollment, 0)) ,
                    SUM(ISNULL(multiracial_enrollment, 0)) ,
                    SUM(ISNULL(unknown_ethnicity_enrollment, 0)) ,
                    SUM(ISNULL(male_enrollment, 0)) ,
                    SUM(ISNULL(female_enrollment, 0)) ,
                    SUM(ISNULL(Total_Enrollment, 0)) 
            FROM    F5A_education_mart_IAK12.dbo.fact_enrollment_school AS fes
                    INNER JOIN dim_time AS dt ON fes.time_key = dt.time_key
                    LEFT OUTER JOIN dim_building AS db ON fes.building_key = db.building_key
            WHERE   year = '2008'
            GROUP BY dt.year 
    --Race 2012 % inc/dec 2011 % inc/dec 2010
    --Caucasian 3000 -.33 4000 .6 2500
    --Black 1000 -.5 2000 .25 1500
    --Asian 100 .5 50 .4 30
    
    SELECT  Race ,
            [2012] = MAX(CASE WHEN a.[Year] = 2012 THEN [Count]
                         END) ,
            [% Inc Dec] = ( MAX(CAST(CASE WHEN a.[Year] = 2011 THEN [Count]
                                     END AS FLOAT))
                            - MAX(CAST(CASE WHEN a.[Year] = 2012 THEN [Count]
                        END AS FLOAT)) )
            / NULLIF(MAX(CAST(CASE WHEN a.[Year] = 2012 THEN [Count]
                       END AS FLOAT)),0) ,
            [2011] = MAX(CASE WHEN a.[Year] = 2011 THEN [Count]
                         END) ,
            [% Inc Dec] = ( MAX(CAST(CASE WHEN a.[Year] = 2010 THEN [Count]
                                     END AS FLOAT))
                            - MAX(CAST(CASE WHEN a.[Year] = 2011 THEN [Count]
                                       END AS FLOAT)) )
            / NULLIF(MAX(CAST(CASE WHEN a.[Year] = 2010 THEN [Count]
                       END AS FLOAT)),0) ,
            [2010] = MAX(CASE WHEN a.[Year] = 2010 THEN [Count]
                         END) ,
            [% Inc Dec] = ( MAX(CAST(CASE WHEN a.[Year] = 2009 THEN [Count]
                                     END AS FLOAT))
                            - MAX(CAST(CASE WHEN a.[Year] = 2010 THEN [Count]
                        END AS FLOAT)) )
            / NULLIF(MAX(CAST(CASE WHEN a.[Year] = 2009 THEN [Count]
                       END AS FLOAT)),0) ,
            [2009] = MAX(CASE WHEN a.[Year] = 2009 THEN [Count]
                         END) ,
            [% Inc Dec] = ( MAX(CAST(CASE WHEN a.[Year] = 2008 THEN [Count]
                                     END AS FLOAT))
                            - MAX(CAST(CASE WHEN a.[Year] = 2009 THEN [Count]
                                       END AS FLOAT)) )
            / NULLIF(MAX(CAST(CASE WHEN a.[Year] = 2009 THEN [Count]
                       END AS FLOAT)), 0)
    FROM    @Data
            CROSS APPLY ( VALUES 
            ( 'Caucasian', caucasian, [Year])
            , ( 'Black', Black, [Year])
            , ( 'Asian', Asian, [Year]) 
            , ('Native', Native, [Year]) 
            , ('Hispanic', Hispanic, [Year]) 
            , ('American Indian', [American Indian], [Year]) 
            , ('Multiracial', multiracial, [Year])
            , ('Unkown', unknown, [Year]) 
            , ('Male', male, [Year]) 
            , ('Female', female, [Year]) 
            , ('Total Enrollment', [Total Enrollment], [Year]) 
            ) a ( Race, [Count], [Year] ) GROUP BY Race
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-28
      • 2012-08-11
      • 2021-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-10
      相关资源
      最近更新 更多