计算雪花中重叠时间会话的不同分钟

如何解决计算雪花中重叠时间会话的不同分钟

我有如下表格:

会话 session_start session_end half_hour_start half_hour_end
A A001 9/13/2020 7:58:00 PM 9/13/2020 晚上 8:10:00 9/13/2020 晚上 8:00:00 2020/9/13 晚上 8:30:00
A A002 9/13/2020 8:02:00 PM 2020/9/13 晚上 8:13:00 9/13/2020 晚上 8:00:00 2020/9/13 晚上 8:30:00
A A003 2020/9/13 晚上 8:27:00 2020/9/13 晚上 8:28:00 9/13/2020 晚上 8:00:00 2020/9/13 晚上 8:30:00
B B001 9/13/2020 晚上 8:20:00 2020/9/13 晚上 8:28:00 9/13/2020 晚上 8:00:00 2020/9/13 晚上 8:30:00
B B002 2020/9/13 晚上 8:28:00 2020/9/13 晚上 8:43:00 9/13/2020 晚上 8:00:00 2020/9/13 晚上 8:30:00

目标是计算每个人在 30 分钟块(half_hour_start - half_hour_end)内的所有会话的不同分钟数。计数从 00 分钟开始,到 29 分钟结束(因此总共有 30 个不同的分钟)。

这样,即使某人的会话从 2020 年 9 月 13 日晚上 8:00:01 开始到 2020 年 9 月 13 日晚上 8:00:05 结束,此人仍将获得 1 分钟的积分- 分钟'00'。我们感兴趣的不是完整分钟数的计数,而是会话发生的所有不同分钟数的计数,即使是部分时间。

我需要得到如下结果:

---旧版本---

distinct_minutes_count
A 14
B 10

---新版本---

distinct_minutes_count
A 16
B 10

(可能来自:

会话 session_start session_end half_hour_start half_hour_end distinct_minutes_count_per_person
A A001 9/13/2020 7:58:00 PM 9/13/2020 晚上 8:10:00 9/13/2020 晚上 8:00:00 2020/9/13 晚上 8:30:00 16
A A002 9/13/2020 8:02:00 PM 2020/9/13 晚上 8:13:00 9/13/2020 晚上 8:00:00 2020/9/13 晚上 8:30:00 16
A A003 2020/9/13 晚上 8:27:00 2020/9/13 晚上 8:28:00 9/13/2020 晚上 8:00:00 2020/9/13 晚上 8:30:00 16
B B001 9/13/2020 晚上 8:20:00 2020/9/13 晚上 8:28:00 9/13/2020 晚上 8:00:00 2020/9/13 晚上 8:30:00 10
B B002 2020/9/13 晚上 8:28:00 2020/9/13 晚上 8:43:00 9/13/2020 晚上 8:00:00 2020/9/13 晚上 8:30:00 10

)

所需的中间步骤可能是:

会话 session_start session_end half_hour_start half_hour_end distinct_minute_per_session distinct_minutes_count_per_session distinct_minute_per_person distinct_minutes_count
A A001 9/13/2020 7:58:00 PM 9/13/2020 晚上 8:10:00 9/13/2020 晚上 8:00:00 2020/9/13 晚上 8:30:00 00,01,02,03,04,05,06,07,08,09,10 11 00,10,11,12,13,27,28 16
A A002 9/13/2020 8:02:00 PM 2020/9/13 晚上 8:13:00 9/13/2020 晚上 8:00:00 2020/9/13 晚上 8:30:00 02,13 12 00,28 16
A A003 2020/9/13 晚上 8:27:00 2020/9/13 晚上 8:28:00 9/13/2020 晚上 8:00:00 2020/9/13 晚上 8:30:00 27,28 2 00,28 16
B B001 9/13/2020 晚上 8:20:00 2020/9/13 晚上 8:28:00 9/13/2020 晚上 8:00:00 2020/9/13 晚上 8:30:00 20,21,22,23,24,25,26,28 9 20,28,29 10
B B002 2020/9/13 晚上 8:28:00 2020/9/13 晚上 8:43:00 9/13/2020 晚上 8:00:00 2020/9/13 晚上 8:30:00 28,29 2 20,29 10

但我没有看到为 Snowflake 中的列创建列表值的选项。

解决方法

以下内容应该可以帮助您完成大部分工作。您可能会在 CTE 中删除很多列 - 我只是将它们放在那里以检查中间步骤。 可能还有很多其他场景不在您的示例数据中,所以我没有检查,但您可能应该例如如果会话 session_start/session_end 完全在另一个会话的持续时间内

WITH TEMP1 AS
    (
        SELECT
            PERSON,SESSION,SESSION_START,SESSION_END,HALF_HOUR_START,HALF_HOUR_END,GREATEST(SESSION_START,HALF_HOUR_START)                                                     CALC_START,LEAST(SESSION_END,HALF_HOUR_END)                                                            CALC_END,DATEDIFF(MINUTE,HALF_HOUR_START),HALF_HOUR_END)) DUR -- Adjust to allow for partial minutes if necessary,by adding 1 to this value,RANK() OVER (PARTITION BY PERSON,HALF_HOUR_START ORDER BY SESSION_START ASC) RNK
        FROM
            SESSION_DATA
    ),TEMP2 AS
    (
        SELECT
            T1.PERSON,T1.SESSION,T1.DUR,T1.RNK,T1.CALC_START,T1.CALC_END,CASE
                WHEN T2.PERSON IS NULL -- Must be first session in the half-hour slot for the person
                    THEN T1.DUR
                    ELSE DATEDIFF(MINUTE,T2.CALC_END,T1.CALC_END)
            END DISTINCT_DUR 
        FROM
            TEMP1 T1
            LEFT OUTER JOIN -- join to previous session within the same half-hour slot for the same user
                TEMP1 T2
                ON
                    T1.PERSON              = T2.PERSON
                    AND T1.HALF_HOUR_START = T2.HALF_HOUR_START
                    AND T1.RNK             = (T2.RNK + 1)
    )
SELECT
    PERSON,SUM(DISTINCT_DUR)
FROM
    TEMP2
GROUP BY
    PERSON
;

评论后编辑

正如我所说,这是一个可以帮助您的起点,我还没有使用会话数据的所有可能组合对此进行测试。如果您对 CASE 语句进行以下更改,它会在您包含会话 A003 时起作用:

,CASE 
  WHEN T2.PERSON IS NULL THEN T1.DUR
  WHEN T1.CALC_START > T2.CALC_END THEN T1.DUR
 ELSE DATEDIFF(MINUTE,T1.CALC_END) END DISTINCT_DUR
,

要生成多行,可以使用一个JS表UDF:

CREATE OR REPLACE FUNCTION generate_minutes(STARTING timestamp,ENDING timestamp)
RETURNS TABLE (V VARCHAR)
LANGUAGE JAVASCRIPT
AS '{
    processRow: function get_params(row,rowWriter,context){
       for(var i=row.STARTING/60/1000; i<=row.ENDING/60/1000; i++) {
           rowWriter.writeRow({V: i}); 
       }
    }
}';


with data as (
select 'A' person,'A001' session,'9/13/2020 7:58:00'::timestamp session_start,'9/13/2020 8:10:00'::timestamp session_end,'9/13/2020 8:00:00'::timestamp half_hour_start,'9/13/2020 8:30:00'::timestamp half_hour_end 
union all select 'A','A002','9/13/2020 8:02:00','9/13/2020 8:13:00','9/13/2020 8:00:00','9/13/2020 8:30:00'
union all select 'A','A003','9/13/2020 8:27:00','9/13/2020 8:28:00','9/13/2020 8:30:00'
)

select person,count(distinct x.v) distinct_minutes
from data,table(generate_minutes(
      greatest(session_start,half_hour_start),least(session_end,timestampadd(minute,-1,half_hour_end)))
     ) x
where session_start<=half_hour_end and session_end >= half_hour_start
group by person

enter image description here

,

所以使用这两个兴趣周期表和会话表分开开始

with periods as (
    select p_from::timestamp_ntz as p_from,p_to::timestamp_ntz as p_to
    from values 
    ('2020-09-13 20:00:00','2020-09-13 20:30:00' ),('2020-09-13 20:30:00','2020-09-13 21:00:00' )
    v(p_from,p_to)
),sessions as (
    select user,session,s_from::timestamp_ntz as s_from,s_to::timestamp_ntz as s_to
    from values 
    ('A','A001','2020-09-13 19:58:00','2020-09-13 20:10:00'),('A','2020-09-13 20:02:00','2020-09-13 20:13:00'),'2020-09-13 20:27:00','2020-09-13 20:28:00'),('B','B001','2020-09-13 20:20:00','B002','2020-09-13 20:28:00','2020-09-13 20:43:00')
    v(user,s_from,s_to)

然后我们首先将它们混合在一起以重新创建您所拥有的 p_s_mix,然后将会话时间修剪到时间段的边界(也就是使用 t_fromt_to 完成)然后我们可以得到那些的日期分钟部分(又名 from_min & `to_min)

),p_s_mix as (
    select s.*,p.*
    from sessions as s
    join periods as p
    where s.s_from < p.p_to and s.s_to > p.p_from
    order by 1,2
),p_s_trim AS (
    select user,session
        --,s_from
        --,s_to,p_from,p_to,greatest(p_from,s_from) as t_from,least(p_to,s_to) as t_to,date_part('minute',t_from) as from_min,t_to) as to_min
    from p_s_mix

然后我们可以将其与预编码的 60 分钟时段的总表混合,并计算不同的分钟数。只是为了好玩,提供了 array_agg 以显示示例中给出的形式的数组。

),gross AS (
    SELECT * from values
    (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16),(17),(18),(19),(20),(21),(22),(23),(24),(25),(26),(27),(28),(29),(30),(31),(32),(33),(34),(35),(36),(37),(38),(39),(40),(41),(42),(43),(44),(45),(46),(47),(48),(49),(50),(51),(52),(53),(54),(55),(56),(57),(58),(59)
    v(slot)
)
select p.user,p.p_from,p.p_to,count(distinct g.slot) as c_mintues,array_agg(distinct g.slot) within group(order by g.slot) as distinct_mintues
 from p_s_trim as p
 join gross as g
    on p.from_min <= g.slot and p.to_min >= g.slot
 group by 1,2,3
 order by 1,3
;

给予:

USER  P_FROM                   P_TO                     C_MINTUES  DISTINCT_MINTUES 
A     2020-09-13 20:00:00.000  2020-09-13 20:30:00.000  16         [ 0,1,3,4,5,6,7,8,9,10,11,12,13,27,28]
B     2020-09-13 20:00:00.000  2020-09-13 20:30:00.000  11         [ 20,21,22,23,24,25,26,28,29,30]
B     2020-09-13 20:30:00.000  2020-09-13 21:00:00.000  14         [ 30,31,32,33,34,35,36,37,38,39,40,41,42,43]

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

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res