微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Clickhouse:减少元组数组以计算平均会话时间

如何解决Clickhouse:减少元组数组以计算平均会话时间

我有很多事件。 每个事件都表示为元组,并且包含session_iddatetime

[
 ('aa','2020-11-08 01:00:01'),('aa','2020-11-08 01:00:03'),'2020-11-08 01:00:05'),('ab','2020-11-09 01:00:00'),'2020-11-09 01:00:05'),'2020-11-09 01:00:15')
]

我需要使用此数组计算平均会话时间。

所以我需要将此数组转换为新数组[(session_id,min(datetime),max(datetime))]

[
 ('aa','2020-11-08 01:00:01','2020-11-09 01:00:00','2020-11-09 01:00:15')
]

然后为每个session_id [(session_id,max(datetime) - min(datetime))]

计算session_time
[
 ('aa',4),15)
]

然后计算平均会话时间((4+15)/2) = 9.5

最好的方法是什么?

解决方法

要获得理想的结果,我将使用数据的关系表示而不是数组。

arrayJoin帮助将数组转换为关系:

SELECT avg(duration)
FROM 
(
    SELECT max(time) - min(time) AS duration
    FROM 
    (
        SELECT 
            data.1 AS id,toDateTime(data.2) AS time
        FROM 
        (
            SELECT arrayJoin([('aa','2020-11-08 01:00:01'),('aa','2020-11-08 01:00:03'),'2020-11-08 01:00:05'),('ab','2020-11-09 01:00:00'),'2020-11-09 01:00:05'),'2020-11-09 01:00:15')]) AS data
        )
    )
    GROUP BY id
)
/*
┌─avg(duration)─┐
│           9.5 │
└───────────────┘
*/

基于数组的决策。考虑到它可能比基于关系的解决方案要慢得多(请在选择最佳解决方案之前先对它们进行检查)。可以使用arrayReduceInRanges函数来改进此实现。

SELECT 
    arraySort(x -> (x.1),data) AS sorted_array,arraySplit((x,y) -> y,sorted_array,arrayMap((x,i) -> if(i = 1,1,if((x.1) = ((sorted_array[i - 1]).1),1)),arrayEnumerate(sorted_array))) AS session_arrays,arrayMap(arr -> arrayReduce('min',arrayMap(x -> (x.2),arr)),session_arrays) AS min_session_times,arrayMap(arr -> arrayReduce('max',session_arrays) AS max_session_times,arrayReduce('avg',y) -> (y - x),min_session_times,max_session_times)) AS avg
FROM 
(
    SELECT [('aa',toDateTime('2020-11-08 01:00:01')),toDateTime('2020-11-08 01:00:03')),toDateTime('2020-11-08 01:00:05')),toDateTime('2020-11-09 01:00:00')),toDateTime('2020-11-09 01:00:05')),toDateTime('2020-11-09 01:00:15'))] AS data
)
/*
Row 1:
──────
sorted_array:      [('aa','2020-11-09 01:00:15')]
session_arrays:    [[('aa','2020-11-08 01:00:05')],[('ab','2020-11-09 01:00:15')]]
min_session_times: ['2020-11-08 01:00:01','2020-11-09 01:00:00']
max_session_times: ['2020-11-08 01:00:05','2020-11-09 01:00:15']
avg:               9.5
*/
,

minMap(data.1,data.2)

select minMap(data.1,data.2) from (
SELECT [('aa','2020-11-09 01:00:15')] AS data)

┌─minMap(tupleElement(data,1),tupleElement(data,2))────────┐
│ (['aa','ab'],['2020-11-08 01:00:01','2020-11-09 01:00:00']) │
└─────────────────────────────────────────────────────────────┘

select minMap(data.1,data.2).2 as x,maxMap(data.1,data.2).2 as y,arrayMap(i,j -> toDateTime(j)-toDateTime(i),x,y) r,r) z
from (
SELECT [('aa','2020-11-09 01:00:15')] AS data)
        
┌─x─────────────────────────────────────────────┬─y─────────────────────────────────────────────┬─r──────┬───z─┐
│ ['2020-11-08 01:00:01','2020-11-09 01:00:00'] │ ['2020-11-08 01:00:05','2020-11-09 01:00:15'] │ [4,15] │ 9.5 │
└───────────────────────────────────────────────┴───────────────────────────────────────────────┴────────┴─────┘

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。