sql—如何按范围计算特定值在每列和分组上出现的次数

1bqhqjot  于 2021-08-09  发布在  Java
关注(0)|答案(1)|浏览(362)

我是新来的,我有个问题:
我有一张有100列的表。我需要计算每列中的值,并计算它们出现的次数,以便根据它们适合的范围进行分组
我有一个这样的表(100列)

+------+------+------+------+------+---------+--------+
| Name | PRB0 | PRB1 | PRB2 | PRB3 | ....... | PRB100 |
+------+------+------+------+------+---------+--------+
| A    |   15 |   6  |   47 |   54 |   ..... |      8 |
| B    |   25 |   22 |   84 |   86 |   ..... |     76 |
| C    |   57 |   57 |   96 |   38 |   ..... |     28 |
+------+------+------+------+------+---------+--------+

需要这样的输出

+------+---------------+----------------+----------------+----------------+-----+-----------------+--+
| Name | Count 0 to 20 | Count 21 to 40 | Count 41 to 60 | Count 61 to 70 | ... | Count 81 to 100 |  |
+------+---------------+----------------+----------------+----------------+-----+-----------------+--+
| A    |             5 |             46 |             87 |             34 | ... |              98 |  |
| B    |             5 |              2 |             34 |             56 | ... |              36 |  |
| C    |             7 |             17 |             56 |             78 | ... |              88 |  |
+------+---------------+----------------+----------------+----------------+-----+-----------------+--+

我们有一个名字:
0到20之间的数字的5倍
在21到40之间的数字出现了46倍
在41到60之间的数字出现了86倍
基本上我需要一些像我们在excel上的函数countif。在excel上,我们只需要指定列的范围和条件。

ycggw6v2

ycggw6v21#

您可以使用横向联接取消PIVOT,然后聚合:

select
    name,
    count(*) filter(where prb between 0  and 20) cnt_00_20,
    count(*) filter(where prb between 21 and 50) cnt_21_20,
    ...,
    count(*) filter(where prb between 81 and 100) cnt_81_100
from mytable t
cross join lateral (values(t.prb0), (t.prb1), ..., (t.prb100)) p(prb)
group by name

但是,请注意,这仍然需要您枚举 values() 表构造函数。如果您想要完全动态的东西,可以使用json。其思想是使用 to_jsonb() ,然后使用 jsonb_each() ; 然后可以进行条件聚合。

select 
    name,
    count(*) filter(where prb::int between 0  and 20) cnt_00_20,
    count(*) filter(where prb::int between 21 and 50) cnt_21_20,
    ...,
    count(*) filter(where prb::int between 81 and 100) cnt_81_100
from mytable t
cross join lateral to_jsonb(t) j(js)
cross join lateral jsonb_each( j.js - 'name') r(col, prb)
group by name

相关问题