ClickHouse 专门计算每个属性的分位数

ClickHouse compute quantile per attribute exclusively

考虑这个数据集:

attr | value
------------
A    | 1
A    | 2
A    | 3
B    | 4
B    | 5
B    | 6
C    | 7
C    | 8
C    | 9

以下查询:

SELECT 
    attr, 
    quantile(0.5)(value) AS quantile
FROM mytable
GROUP BY attr

每个属性给我 50% 的分位数

attr | quantile
---------------
A    | 2
B    | 5
C    | 8

但我想获得 50% 的分位数,而没有每个 attr 的 attr 值。所以我需要 return

的查询
attr | quantile
---------------
A    | 7
B    | 4
C    | 7

因此,对于 A,它根据属于 A

的所有值计算分位数

第一个查询会 return

你好像打错了分位数 - 应该是 0.6 而不是 0.5,那么这个查询 returns所需结果:(A = 7, B = 4, C = 7).

SELECT groupArray(v) values_per_attr,
  arrayEnumerate(values_per_attr) indexes,
  arrayMap(groupIndex -> (values_per_attr[groupIndex].1, arrayReduce('groupArrayArray', arrayFilter((v, i) -> i != groupIndex, arrayMap(v -> v.2, values_per_attr), indexes))), indexes) exclusive_values_per_attr,
  arrayMap(v -> (v.1, arrayReduce('quantile(0.5)', v.2)), exclusive_values_per_attr) result
FROM
(
    SELECT (attr, groupArray(value)) AS v
    FROM
    (
        /* Emulate test dataset.
        attr | value
        ------------
        A    | 1
        A    | 2
        A    | 3
        B    | 4
        B    | 5
        B    | 6
        C    | 7
        C    | 8
        C    | 9        
        */
        SELECT
            if((number / 4) < 1, 'A', if((number / 7) < 1, 'B', 'C')) AS attr,
            number AS value
        FROM numbers(1, 9)
    )
    GROUP BY attr
)
FORMAT Vertical;
/*
Result: 

Row 1:
──────
values_per_attr:           [('B',[4,5,6]),('C',[7,8,9]),('A',[1,2,3])]
indexes:                   [1,2,3]
exclusive_values_per_attr: [('B',[7,8,9,1,2,3]),('C',[4,5,6,1,2,3]),('A',[4,5,6,7,8,9])]
result:                    [('B',5),('C',3.5),('A',6.5)]
*/