【问题标题】:Division with Aggregate Functions in SQL Not Behaving as ExpectedSQL 中聚合函数的除法不符合预期
【发布时间】:2012-12-28 21:13:46
【问题描述】:

我正在尝试在 SQL Server 2008 R2 中做一些交叉表。这部分没问题,但是,如果我尝试获取每个单元格的百分比,我会遇到问题。

这是一个提炼的用例:一项调查,人们给出他们最喜欢的颜色和最喜欢的水果。我想知道有多少人喜欢给定的水果和给定的颜色:

with survey as (
    select 'banana' fav_fruit, 'yellow' fav_color
     union select 'banana', 'red'
     union select 'apple', 'yellow'
     union select 'grape', 'red'
     union select 'apple', 'blue'
     union select 'orange', 'purple'
     union select 'pomegranate', 'green'
)
select
    s.fav_color, 
    sum(case 
          when s.fav_fruit = 'banana' then 1
          else 0
        end) as banana, 
    sum(case 
           when s.fav_fruit = 'banana' then 1
           else 0
         end) / sum(1)   -- why does division always yield 0? "+", "-", and "*" all behave as expected.
         * 100 as banana_pct,
     sum(1) as total
from 
    survey s
group by
    s.fav_color;

结果:

fav_color   banana banana_pct  total
------------------------------------
blue        0      0            1
green       0      0            1
purple      0      0            1
red         1      0            2
yellow      1      0            2

我所期待的:

fav_color   banana banana_pct  total
------------------------------------
blue        0      0           1
green       0      0           1
purple      0      0           1
red         1      50          2
yellow      1      50          2

请帮助我得到我所期望的?

【问题讨论】:

    标签: sql sql-server aggregate-functions division crosstab


    【解决方案1】:

    您正在使用 SQL Server。这是一个更简单的示例,可以复制该问题:

    select 1/2
    

    SQL Server 进行整数除法。

    将分母替换为sum(1.0) 或sum(cast 1 as float) 或sum(1e0) 而不是sum(1)。

    至少与我的预期相反,SQL Server 将带小数点的数字存储为数字/十进制类型(请参阅here)而不是float。固定的小数位数可能会影响后续操作。

    【讨论】:

    • 好伤心。这将是一个稍微简化的示例。我什至没有想过要把我的测试分解到那么远。 ;-)
    【解决方案2】:

    查询:

    SQLFIddleexample

    SELECT s.fav_color,
           sum( CASE WHEN s.fav_fruit = 'banana' THEN 1 ELSE 0 END ) AS banana,
           sum( CASE WHEN s.fav_fruit = 'banana' THEN 1 ELSE 0 END) / sum(1.00) -- why does division always yield 0? "+", "-", and "*" all behave as expected.
     * 100 AS banana_pct,
       sum(1) AS total
    FROM survey s
    GROUP BY s.fav_color
    

    结果:

    | FAV_COLOR | BANANA | BANANA_PCT | TOTAL |
    -------------------------------------------
    |      blue |      0 |          0 |     1 |
    |     green |      0 |          0 |     1 |
    |    purple |      0 |          0 |     1 |
    |       red |      1 |         50 |     2 |
    |    yellow |      1 |         50 |     2 |
    

    【讨论】:

      【解决方案3】:

      我最近发现了 IIF 函数。它使事情变得更清洁。以上面贾斯汀的例子:

      SELECT s.fav_color,
             sum( IIF(s.fav_fruit = 'banana', 1,0) AS banana,
             sum( IIF(s.fav_fruit = 'banana', 1,0) / sum(1.00) 
       * 100 AS banana_pct,
         sum(1) AS total
      FROM survey s
      GROUP BY s.fav_color
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-05-10
        • 1970-01-01
        • 1970-01-01
        • 2015-10-29
        • 2014-09-22
        • 2021-10-04
        • 2013-08-14
        相关资源
        最近更新 更多