【问题标题】:Aggregate query over multiple columns (one is an array) in clickhouse在clickhouse中对多列(一个是数组)进行聚合查询
【发布时间】:2020-12-23 15:36:52
【问题描述】:

我正在尝试获取每个 att1 和 att2 列的聚合值,以及 att3 列中数组的每个值。

我试过了:

create table test(value Float32, att1 String, att2 String, att3 Array(String))
 ENGINE=MergeTree() ORDER BY ();
INSERT INTO test VALUES (2.0, 'a', 'Z', ['sports', 'office', 'anothertag'])
INSERT INTO test VALUES (4.0, 'b', 'X', ['sports', 'office', 'tag'])
INSERT INTO test VALUES (6.0, 'b', 'X', ['sports', 'internet', 'planes'])
SELECT * from test;
┌─value─┬─att1─┬─att2─┬─att3───────────────────────────┐
│     6 │ b    │ X    │ ['sports','internet','planes'] │
└───────┴──────┴──────┴────────────────────────────────┘
┌─value─┬─att1─┬─att2─┬─att3─────────────────────────────┐
│     2 │ a    │ Z    │ ['sports','office','anothertag'] │
└───────┴──────┴──────┴──────────────────────────────────┘
┌─value─┬─att1─┬─att2─┬─att3──────────────────────┐
│     4 │ b    │ X    │ ['sports','office','tag'] │
└───────┴──────┴──────┴───────────────────────────┘

我想获取每个不同属性的聚合 -sum(value)-。

我让它适用于 att1 和 att2 列:

SELECT
    att1,
    att2,
    sum(value)
FROM test
GROUP BY
    att1,
    att2
    WITH CUBE

结果:

┌─att1─┬─att2─┬─sum(value)─┐
│ b    │ X    │         10 │
│ a    │ Z    │          2 │
└──────┴──────┴────────────┘
┌─att1─┬─att2─┬─sum(value)─┐
│ a    │      │          2 │
│ b    │      │         10 │
└──────┴──────┴────────────┘
┌─att1─┬─att2─┬─sum(value)─┐
│      │ Z    │          2 │
│      │ X    │         10 │
└──────┴──────┴────────────┘
┌─att1─┬─att2─┬─sum(value)─┐
│      │      │         12 │
└──────┴──────┴────────────┘

这给了我更多的需要,但结果二和三给出了正确的结果。

但我还需要 att3 上每个值的值,我让它在另一个查询中工作,但是在尝试进行单个查询时:

SELECT
    att1,
    att2,
    arrayJoin(att3) AS tags,
    sum(value)
FROM test
GROUP BY
    att1,
    att2,
    tags
    WITH CUBE

这给出了(除其他外):

┌─att1─┬─att2─┬─tags─┬─sum(value)─┐
│ a    │      │      │          6 │
│ b    │      │      │         30 │
└──────┴──────┴──────┴────────────┘

┌─att1─┬─att2─┬─tags───────┬─sum(value)─┐
│      │      │ tag        │          4 │
│      │      │ anothertag │          2 │
│      │      │ planes     │          6 │
│      │      │ sports     │         12 │
│      │      │ internet   │          6 │
│      │      │ office     │          6 │
└──────┴──────┴────────────┴────────────┘

由于 arrayJoin 'unfolds' 数组成行,现在 att1 中 sum(value) 的值不准确。

我也尝试了LEFT ARRAY JOIN 语法,结果相同。

更新:

理想的结果是这样的:

┌─'att1'─┬─'att2'─┬─'tags'─┬─'sum(value)'─┐
│    a   │        │        │         2    │
│    b   │        │        │         10   │
│        │    X   │        │         10   │
│        │    Z   │        │         2    │
│        │        │ sports │         12   │
│        │        │ office │         6    │
│        │        │ anot.. │         2    │
│        │        │ tag    │         4    │
│        │        │internet│         6    │
│        │        │planes  │         6    │
└────────┴────────┴────────┴──────────────┘

可以在不同的行(结果)中,但最好在一个查询中。

【问题讨论】:

    标签: clickhouse


    【解决方案1】:
    SELECT
        sumMap(([att1], [value])) AS r1,
        sumMap(([att2], [value])) AS r2,
        sumMap((att3, replicate(value, att3))) AS r3
    FROM test
    ┌─r1─────────────────┬─r2─────────────────┬─r3──────────────────────────────────────────────────────────────────────────┐
    │ (['a','b'],[2,10]) │ (['X','Z'],[10,2]) │ (['anothertag','internet','office','planes','sports','tag'],[2,6,6,6,12,4]) │
    └────────────────────┴────────────────────┴─────────────────────────────────────────────────────────────────────────────┘
    
    
    
    SELECT
        (arrayJoin(arrayZip((arrayJoin([sumMap(([att1], [value])), sumMap(([att2], [value])), sumMap((att3, replicate(value, att3)))]) AS r).1, r.2)) AS x).1 AS y,
        x.2 AS z
    FROM test
    ┌─y──────────┬──z─┐
    │ a          │  2 │
    │ b          │ 10 │
    │ X          │ 10 │
    │ Z          │  2 │
    │ anothertag │  2 │
    │ internet   │  6 │
    │ office     │  6 │
    │ planes     │  6 │
    │ sports     │ 12 │
    │ tag        │  4 │
    └────────────┴────┘
    

    【讨论】:

    • 标签组有重复项,所以它没有像我预期的那样直接工作。在实际数据中,它会按行爆炸。
    • @chaim 那么我真的不明白你对结果的期望。
    • 请解释一下这段代码是如何解决问题的
    • @DennyCrane 我已经用可能需要的输出更新了这个问题。它应该比我解释清楚:)
    • @chaim 你需要 summap 函数
    【解决方案2】:

    我认为更直接的方法是结合两个查询:

    SELECT
        att1,
        att2,
        '' AS tags,
        sum(value)
    FROM test
    GROUP BY
        att1,
        att2
        WITH CUBE
    UNION ALL
    SELECT
        '' AS att1,
        '' AS att2,
        arrayJoin(att3) AS tags,
        sum(value)
    FROM test
    GROUP BY tags
    
    /*
    ┌─att1─┬─att2─┬─tags───────┬─sum(value)─┐
    │      │      │ internet   │          6 │
    │      │      │ sports     │         12 │
    │      │      │ office     │          6 │
    │      │      │ tag        │          4 │
    │      │      │ planes     │          6 │
    │      │      │ anothertag │          2 │
    └──────┴──────┴────────────┴────────────┘
    ┌─att1─┬─att2─┬─tags─┬─sum(value)─┐
    │ b    │ X    │      │         10 │
    │ a    │ Z    │      │          2 │
    └──────┴──────┴──────┴────────────┘
    ┌─att1─┬─att2─┬─tags─┬─sum(value)─┐
    │ a    │      │      │          2 │
    │ b    │      │      │         10 │
    └──────┴──────┴──────┴────────────┘
    ┌─att1─┬─att2─┬─tags─┬─sum(value)─┐
    │      │ Z    │      │          2 │
    │      │ X    │      │         10 │
    └──────┴──────┴──────┴────────────┘
    ┌─att1─┬─att2─┬─tags─┬─sum(value)─┐
    │      │      │      │         12 │
    └──────┴──────┴──────┴────────────┘
    
    */
    

    【讨论】:

    • 简单,聪明。其他答案有点高性能。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-30
    • 2020-03-09
    • 1970-01-01
    • 2018-10-13
    • 2019-01-10
    • 2015-01-15
    • 1970-01-01
    相关资源
    最近更新 更多