【问题标题】:Clickhouse running diff with groupingClickhouse 使用分组运行差异
【发布时间】:2019-01-22 04:40:33
【问题描述】:

一般任务

一个表由三列组成(timekeyvalue)。任务是计算每个键的运行差异。 所以,从输入

---------------
| time | key | value |
---------------
| 1    | A   | 4     |
| 2    | B   | 1     |
| 3    | A   | 6     |
| 4    | A   | 7     |
| 5    | B   | 3     |
| 6    | B   | 7     |

希望得到

----------------------
| key | value | delta |
----------------------
| A   | 4     |  0    |
| B   | 1     |  0    |
| A   | 6     |  2    |
| A   | 7     |  1    |
| B   | 3     |  2    |
| B   | 7     |  4    |

方法

  1. runningDifference 函数。工作,如果密钥是固定的。所以我们可以

    select *, runningDifference(value) from
        (SELECT key, value from table where key = 'A' order by time)
    

    请注意,这里需要子查询。当您想为不同的 keys

    获取此解决方案时,此解决方案会受到影响
  2. groupArray.

    select key, groupArray(value) from
        (SELECT key, value from table order by time)
        group by key
    

    所以,现在我们得到一个键和一个带有这个键的元素数组。很好。

    但是如何计算滑动差?如果我们能做到这一点,那么ARRAY JOIN 将引导我们找到结果。

    或者我们甚至可以使用 zip 数组本身,然后应用 lambda(为此我们有 arrayMap)但是......我们没有任何 zip 替代方案。

有什么想法吗? 提前致谢。

【问题讨论】:

    标签: clickhouse


    【解决方案1】:

    数组解决方案:

    WITH 
       groupArray(value) as time_sorted_vals,
       arrayEnumerate(time_sorted_vals) as indexes,
       arrayMap( i -> time_sorted_vals[i] - time_sorted_vals[i-1], indexes) as running_diffs
    SELECT 
       key,
       running_diffs
    FROM 
        (SELECT key, value from table order by time)
    GROUP by key
    

    其他选项(在每个组内分别进行排序,这在很多情况下更佳)

    WITH
       groupArray( tuple(value,time) ) as val_time_tuples,
       arraySort( x -> x.2, val_time_tuples ) as val_time_tuples_sorted,
       arrayMap( t -> t.1, indexes) as time_sorted_vals,
       arrayEnumerate(time_sorted_vals) as indexes,
       arrayMap( i -> time_sorted_vals[i] - time_sorted_vals[i-1], indexes) as running_diffs
    SELECT 
       key,
       running_diffs
    FROM 
       time
    GROUP by key
    

    然后您可以在结果上应用 ARRAY JOIN。

    【讨论】:

    • 嗨,我想知道如果我们还想在结果中包含time 列,查询会是什么样子,意思是:| time | key | value | delta |
    • 这个答案是几年前发布的,今天是 2021 年 9 月 29 日,我们可以使用 arrayDifference 而不是 arrayMap。我们可以ARRAY JOIN 这样我们就可以得到一个表格结果而不是嵌套数组。那就是:
    • 查看我发布的答案。
    【解决方案2】:

    最近我也遇到了这个问题,Clickhouse 提供了函数arrayDifference

    WITH 
       groupArray(value) as vals
       arrayDifference(vals) as running_diffs
    SELECT 
       key,
       running_diffs
    FROM 
        (SELECT key, value from table order by time)
    GROUP by key
    

    【讨论】:

    • 你好,是的,这个问题已经很久没有问过了。让我指出您的回答并没有解决最初的问题:您的查询为每个键生成一个差异数组,虽然希望保持整体顺序,但简单的数组连接不会给您这样的结果。跨度>
    【解决方案3】:

    这个问题是几年前发布的,今天,2021 年 9 月 29 日,我们可以使用 arrayDifference 代替 arrayMap。而且我们可以ARRAY JOIN 这样我们就可以得到一个表格的结果而不是一个嵌套的数组。

    SELECT key, sorted_time, time_sorted_vals, running_diffs
    FROM (
    WITH
       groupArray( tuple(value,time) ) as val_time_tuples,
       arraySort( x -> x.2, val_time_tuples ) as val_time_tuples_sorted,
       arrayMap( t -> t.1, val_time_tuples_sorted) as time_sorted_vals,
       arrayMap( t -> t.2, val_time_tuples_sorted) as sorted_time,
       arrayDifference(time_sorted_vals) as running_diffs
    SELECT 
       key,
       sorted_time,
       time_sorted_vals,
       running_diffs
    FROM 
       table_name
    GROUP by key)
    ARRAY JOIN sorted_time, time_sorted_vals, running_diffs
    

    唯一的限制是value 列不应该是可为空的类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-21
      • 2011-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多