PostgreSQL Group按类别,计数和计算百分比值

时间:2017-10-19 20:42:53

标签: sql postgresql

我有一张桌子moves

uuid | tag | ...
-----| ----|----
abc  | 520 | ...
def  | 510 | ...
ghi  | 500 | ...
jkl  | 310 | ...
mno  | 200 | ...

tag代表移动的类型。我们正在谈论沙滩排球的举动。第一个数字,例如520中的5,是类别。在这种情况下“服务”。我总共有六个类别:

  1. 攻击(类别1,例如100110120
  2. 区块(类别2)
  3. Dig(类别3)
  4. 接待(类别4)
  5. 服务(类别5)
  6. 设定(类别6)
  7. 最后一个数字,即520的20,是结果。在这种情况下“赢”。每个类别都有3种可能的结果:

    1. 错误(00
    2. 零(10
    3. 赢(20
    4. 以下是上表中的标签

      1. 520 - 服务胜利(这是一个王牌)
      2. 510 - Service Zero
      3. 500 - 服务错误
      4. 310 - Dig Zero
      5. 200 - 阻止错误
      6. 以下是我想要的内容:以绝对值和相对值为每个类别提供错误,零,赢的数量。

        我尝试了以下

        select *,
            (attack_error::float / attacks::float * 100) as attack_error_percentage,
            (attack_zero::float / attacks::float * 100) as attack_zero_percentage,
            (attack_win::float / attacks::float * 100) as attack_win_percentage
            from (
                select
                    count(*) filter (where tag = 100) as attack_error,
                    count(*) filter (where tag = 110) as attack_zero,
                    count(*) filter (where tag = 120) as attack_win,
                    count(*) filter (where tag = 100 or tag = 110 or tag = 120) as attacks
                from moves
                where match_uuid = 'd7eea231-a63d-4d73-b48f-5ca8541ec9cf' and set = 1
            )
        as attack_stats
        

        并得到类似的东西

        att_error | att_zero | att_win | total | att_error_% | att_zero_% | att_win_%
        ----------|----------|---------|-------|-------------|------------|----------
        1         | 3        | 13      | 17    | 5.88        | 17.65      | 76.47
        

        然而它感觉不对,因为我必须一次又一次地对所有不同类别的所有结果重复查询。

        我真正想要得到的是这样的。

        category | error | zero | win | total | error_% | zero_% | win_%
        ---------|-------|------|-----|-------|---------|--------|------
        1        | 2     | 4    | 6   | 12    | 0.16    | 0.33   | 0.5
        2        | 3     | 8    | 13  | 24    | 0.125   | 0.33   | 0.54
        3        | ...   | ...  | ... | ...   | ...     | ...    | ...
        4        | ...   | ...  | ... | ...   | ...     | ...    | ...
        5        | ...   | ...  | ... | ...   | ...     | ...    | ...
        6        | ...   | ...  | ... | ...   | ...     | ...    | ...
        

        有什么想法吗?

1 个答案:

答案 0 :(得分:1)

考虑使用CASE语句有条件地创建类别列,并将其作为GROUP BY包含在派生表聚合查询中

select *,
    (error::float / total::float * 100) as error_percentage,
    (zero::float / total::float * 100) as zero_percentage,
    (win::float / total::float * 100) as win_percentage
    from (
        select
            case substring(tag::text, 1, 1)
                 when '1' then 'Attack' 
                 when '2' then 'Block' 
                 when '3' then 'Dig' 
                 when '4' then 'Reception' 
                 when '5' then 'Service' 
                 when '6' then 'Setting' 
            end as category,
            count(*) filter (where tag - round(tag/100, 0)*100 = 0) as error,
            count(*) filter (where tag - round(tag/100, 0)*100 = 10) as zero,
            count(*) filter (where tag - round(tag/100, 0)*100 = 20) as win,
            count(*) filter (where tag - round(tag/100, 0)*100 <= 20) as total
        from moves
        where match_uuid = 'd7eea231-a63d-4d73-b48f-5ca8541ec9cf' and set = 1
        group by
            case substring(tag::text, 1, 1)
                 when '1' then 'Attack' 
                 when '2' then 'Block' 
                 when '3' then 'Dig' 
                 when '4' then 'Reception' 
                 when '5' then 'Service' 
                 when '6' then 'Setting' 
            end
    )
as attack_stats
相关问题