【问题标题】:How to handle nested fields in Clickhouse's AggregatingMergeTree Materialized View?如何处理 Clickhouse 的 AggregatingMergeTree 物化视图中的嵌套字段?
【发布时间】:2020-07-16 16:38:02
【问题描述】:

有没有办法在 AggregatedMergeTree 物化视图中的 Clickhouse 中组合(连接)组中的 Nested 字段?

想象一下,我有一个表,其架构(简化)如下:

CREATE TABLE test
(
    key1 String,
    key2 String,
    clicks Int32,
    points Nested(x Int32, y Int32)
) Engine = Log

我希望能够使用AggregatingMergeTree 生成一个物化视图,通过“连接”它们来组合嵌套字段(好像嵌套记录可以像某些 SQL 方言那样连接为复杂值)。

如果我将其作为查询进行,则有可能:

SELECT 
    key1,
    key2,
    arrayMap(p -> p.1, points) as x,
    arrayMap(p -> p.2, points) as y
FROM
(
    SELECT  
        key1,
        key2,
        groupArray(tuple(x, y)) as points
    FROM
    (
        SELECT 
            key1, key2, points.x as x, points.y as y
        FROM test 
        ARRAY JOIN points
    )
    GROUP BY key1, key2
)

有没有办法在基于AggregatingMergeTree 引擎的物化视图中使用的查询中表达这一点?我能想到的最好的方法是这样的:

CREATE MATERIALIZED VIEW testagg1
  engine = AggregatingMergeTree partition by key1 order by (key1, key2)
AS 
SELECT
    key1,
    key2,
    sumState(clicks) as clicks,
    groupArrayState(points.x) as `points.x`,
    groupArrayState(points.y) as `points.y`
FROM test
GROUP BY key1, key2

然后我可以使用这个查询得到扁平化的表单:

SELECT 
    arrayMap(p -> p.1, arrayZip(x, y)) as x1,
    arrayMap(p -> p.2, arrayZip(x, y)) as y1
FROM
(
    SELECT 
        key1,
        key2,
        groupArrayMerge(`points.x`) as x, 
        groupArrayMerge(`points.y`) as y 
    FROM testagg1
    GROUP BY key1, key2
) as points 
ARRAY JOIN x, y

它有效,但似乎有点复杂。

  • 有没有更简单、更好的方法来做到这一点?
  • 上面使用的groupArrayStategroupArrayMerge 聚合是否保证以保持并行数组中 x/y 字段的相同顺序?

【问题讨论】:

    标签: clickhouse


    【解决方案1】:

    Nested(x Int32, y Int32) -- 是 create table 命令减少数组样板的语法糖。

    desc test
    ┌─name─────┬─type─────────┬
    │ key1     │ String       │
    │ key2     │ String       │
    │ clicks   │ Int32        │
    │ points.x │ Array(Int32) │
    │ points.y │ Array(Int32) │
    └──────────┴──────────────┴
    

    我能想到的最好的方法是这样的: groupArrayState(points.x) 作为points.x, groupArrayState(points.y) as points.y

    这是唯一的方法。这是官方/正确的 CH 方式。

    上面使用的聚合保证保持相同 并行数组中 x/y 字段的排序?

    是的,这是有保证的。

    选择 arrayMap(p -> p.1, arrayZip(x, y)) 作为 x1, arrayMap(p -> p.2, arrayZip(x, y)) as y1

    和这个一样

    选择 x,y

    不是吗?

    【讨论】:

    • 感谢丹尼斯的快速回复。是的,这个:sql SELECT arrayMap(p -> p.1, arrayZip(x, y)) as x1, arrayMap(p -> p.2, arrayZip(x, y)) as y1
    • 并且您不需要数组映射来提取元组元素。试试select [(1,2),(3,4)] a, a.1, a.2
    猜你喜欢
    • 2019-08-12
    • 2019-01-28
    • 2021-06-13
    • 2018-12-28
    • 1970-01-01
    • 2020-06-25
    • 2021-11-28
    • 2021-12-06
    • 2018-11-10
    相关资源
    最近更新 更多