【问题标题】:Count the number of sessions over the trailing X days计算过去 X 天的会话数
【发布时间】:2017-04-02 15:40:26
【问题描述】:

我的数据库中有一个客户连接日志表,我试图每天计算每个客户在过去 7 天内建立的连接数。我正在使用的源表的架构为

uuid, sessionuid, connection_timestamp

我想要的输出是

uuid, _date, total_connections_over_trailing_seven_days,

这样我就可以查看给定客户帐户和给定日期,该人在过去七天(或其他任何天)内连接了多少次。

我为此编写的查询是

SELECT
  uuid, 
  connection_timestamp::date as _date, 
  COUNT(sessionuid) OVER (ORDER BY timestamp_session ROWS 6 PRECEDING) as trailing_seven_day_session_count
FROM connection_history_table

但是当我执行这个查询时,我会为每个用户和源表中的每个 connection_timestamp 获得一个单独的行,而不是每个唯一的 connection_timestamp::date 的单个记录。此外, trailing_seven_day_session_count 中的值从 1 增加到最大值 7(如果给定日期至少有 7 个会话),但此后不再增加。所以看起来我在计算某一天的会话数,但只计算前 7 个会话。

uuid     _date              trailing_seven_day_session_count
16398   2015-02-18 00:00:00 1
16398   2015-02-18 00:00:00 2
16398   2015-02-18 00:00:00 3
16398   2015-02-18 00:00:00 4
16398   2015-02-18 00:00:00 5
16398   2015-02-18 00:00:00 6
16398   2015-02-18 00:00:00 7
16398   2015-02-18 00:00:00 8
16398   2015-02-18 00:00:00 8
16398   2015-02-25 00:00:00 1
16398   2015-02-25 00:00:00 2
16398   2015-02-25 00:00:00 3
16398   2015-02-25 00:00:00 4
16398   2015-02-25 00:00:00 5
16398   2015-02-25 00:00:00 6
16398   2015-02-25 00:00:00 7
16398   2015-02-25 00:00:00 8
16398   2015-02-25 00:00:00 8

我是使用窗口函数的新手,我不清楚我在这里做错了什么。我尝试通过 connection_timestamp::date 进行分区,但这也无济于事。我基本上抓住了稻草,但没有成功。

谢谢, 布拉德

【问题讨论】:

    标签: postgresql amazon-redshift


    【解决方案1】:

    也许您需要计算每天的会话数,然后计算前几天的总和。像这样的:

    select
        uuid,
        day,
        sum(sessions) over (partition by uuid order by day rows 6 preceding) as trailing_seven_day_session_count
    from (select uuid, connection_timestamp::date as day, count(*) sessions
        from connection_history_table
        group by 1,2)
    order by 1,2
    

    关于 Brad 关于稀疏数据的评论,这是一种可能的方法。它生成零记录来填充天数,因此回顾一组记录将与天数相关。没跑过,但应该很接近了。由于它生成天数,因此需要一个需要调整的整体时间范围。我不确定我的日期范围和填充是否正确...它正在尝试获取 37 天的数据以生成 30 天的记录。

    with days as (
        -- hack to generate days in redshift like a generate_series function
        select (dateadd(day, -row_number() over (order by true), sysdate::date)) as day
                from stv_blocklist limit 37
    ),
    day_counts as (
        select uuid, connection_timestamp::date as day, count(*) sessions
        from connection_history_table
        where connection_timestamp >= sysdate-37
        group by 1,2
    ),
    zero_days as (
        select s.uuid, d.day, 0 as sessions
        from (
            select distinct uuid from connection_history_table
            where connection_timestamp >= sysdate-37
        ) s
        cross join days d
    )
    select
        uuid,
        day,
        sum(sessions) over (partition by uuid order by day rows 6 preceding) as trailing_seven_day_session_count
    from (
        select uuid, day, sessions from day_counts
        union all
        select uuid, day, sessions from zero_days z
            left join day_counts c on z.uuid=c.uuid and z.day=c.day
            where c.uuid is null
    )
    having day >= sysdate-30
    order by 1,2
    

    【讨论】:

    • 是的,我尝试了类似的方法,但它并没有得到我想要的,因为它超过了前六行,而且我不一定每天都有一行。我每天只有一个用户播放的行。所以我必须想出一个完全不同的解决方案。不过感谢您的帮助。我将支持您的解决方案并接受它,因为它解决了我发布的原始问题,而不是我实际遇到的问题。 :
    • 它必须是一次拍摄还是您可以迭代地运行查询...比如每天一次?如果你可以每天都这样做,你可以在内部选择中添加一个 where 子句,它只选择连接时间戳 >= sysdate-7 的记录来获得你想要的。
    • 添加了 janky 查询来处理空天数。
    猜你喜欢
    • 2016-03-06
    • 2021-06-08
    • 1970-01-01
    • 2015-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-10
    • 2020-08-23
    相关资源
    最近更新 更多