汇总一次取k的行的所有组合

时间:2019-01-16 00:13:07

标签: postgresql combinatorics

我正在尝试为表中行的子集的字段计算聚合函数。问题是我想一次找到k个行的每个组合的均值-因此,对于所有行,我想找到(说)10行的每个组合的均值。所以:

 id | count
----|------
  1 |  5
  2 |  3
  3 |  6
...
 30 | 16

应该给我

ids 1..10的平均值; ID 1,3..11; ID 1、4..12等。我知道这会产生很多行。

从数组中找到combinations有一些答案。我可以通过编程来做到这一点,一次获取30个ID 10,然后SELECT对其进行编码。是否可以使用PARTITION BYTABLESAMPLE或其他函数(例如python的itertools.combinations())来做到这一点? (TABLESAMPLE本身并不能保证我所能选择的行子集。)

1 个答案:

答案 0 :(得分:2)

引用的答案中描述的方法是静态的。一个更方便的解决方案可能是使用递归。

示例数据:

drop table if exists my_table;
create table my_table(id int primary key, number int);
insert into my_table values
(1, 5), 
(2, 3), 
(3, 6), 
(4, 9), 
(5, 2);

查询可在5个元素集中找到2个元素子集(k组合,k = 2):

with recursive recur as (
    select 
        id, 
        array[id] as combination, 
        array[number] as numbers, 
        number as sum
    from my_table
union all
    select 
        t.id, 
        combination || t.id, 
        numbers || t.number, 
        sum+ number
    from my_table t
    join recur r on r.id < t.id 
    and cardinality(combination) < 2            -- param k
)
select combination, numbers, sum/2.0 as average -- param k
from recur
where cardinality(combination) = 2              -- param k

 combination | numbers |      average       
-------------+---------+--------------------
 {1,2}       | {5,3}   | 4.0000000000000000
 {1,3}       | {5,6}   | 5.5000000000000000
 {1,4}       | {5,9}   | 7.0000000000000000
 {1,5}       | {5,2}   | 3.5000000000000000
 {2,3}       | {3,6}   | 4.5000000000000000
 {2,4}       | {3,9}   | 6.0000000000000000
 {2,5}       | {3,2}   | 2.5000000000000000
 {3,4}       | {6,9}   | 7.5000000000000000
 {3,5}       | {6,2}   | 4.0000000000000000
 {4,5}       | {9,2}   | 5.5000000000000000
(10 rows)   

对于k = 3的相同查询给出:

 combination | numbers |      average       
-------------+---------+--------------------
 {1,2,3}     | {5,3,6} | 4.6666666666666667
 {1,2,4}     | {5,3,9} | 5.6666666666666667
 {1,2,5}     | {5,3,2} | 3.3333333333333333
 {1,3,4}     | {5,6,9} | 6.6666666666666667
 {1,3,5}     | {5,6,2} | 4.3333333333333333
 {1,4,5}     | {5,9,2} | 5.3333333333333333
 {2,3,4}     | {3,6,9} | 6.0000000000000000
 {2,3,5}     | {3,6,2} | 3.6666666666666667
 {2,4,5}     | {3,9,2} | 4.6666666666666667
 {3,4,5}     | {6,9,2} | 5.6666666666666667
(10 rows)

当然,如果不需要numbers,则可以将其从查询中删除。