【问题标题】:Group pageviews into sessions using timestamp difference使用时间戳差异将综合浏览量分组到会话中
【发布时间】:2018-11-15 08:52:24
【问题描述】:

我有一个包含 3 个字段的表:user_id、页面和时间戳,如下所示:

user_id     page        timestamp
1234567     home.all    2018-03-01 00:10
7541231     task.now    2018-03-01 03:51
7541231     home.all    2018-03-01 03:53
4544731     talk.wow    2018-03-01 04:56
4544731     task.now    2018-03-01 05:01
4544731     home.all    2018-03-01 05:02
4544731     bla.home    2018-03-01 05:26
4544731     home.all    2018-03-01 06:40

时间戳是具有给定 ID 的用户在网站上加载给定页面的时间。每个观察结果都是一次网页浏览命中。

我需要为每个观察分配一个会话 ID。每个会话的每个会话 id 应该是唯一的,其中一个会话是一组综合浏览量,其中最接近彼此的时间戳的时差不超过 3600 秒,发生在 相同的 user_id .

结果应该是这样的:

user_id     page        timestamp           session_id
1234567     home.all    2018-03-01 00:10    1234567-2018030100100010
7541231     task.now    2018-03-01 03:51    7541231-2018030103510353
7541231     home.all    2018-03-01 03:53    7541231-2018030103510353
4544731     talk.wow    2018-03-01 04:56    4544731-2018030104560526
4544731     task.now    2018-03-01 05:01    4544731-2018030104560526
4544731     home.all    2018-03-01 05:02    4544731-2018030104560526
4544731     bla.home    2018-03-01 05:26    4544731-2018030104560526
4544731     home.all    2018-03-01 06:40    4544731-2018030106400640

请您对此提出任何疑问吗?

【问题讨论】:

    标签: sql postgresql timestamp sessionid pageviews


    【解决方案1】:

    如果您可以确保 user_idtimestamp 对是唯一的,以下可能对您有用。

    WITH cte AS
    (
    SELECT h1.user_id,
           h1.page,
           h1.timestamp,
           coalesce(h1.timestamp - h2.timestamp <= INTERVAL '3600 SECONDS', false) shares_session_with_previous,
           coalesce(h4.timestamp - h1.timestamp <= INTERVAL '3600 SECONDS', false) shares_session_with_next
           FROM hit h1
                LEFT JOIN hit h2
                          ON h2.user_id = h1.user_id
                             AND h2.timestamp = (SELECT max(h3.timestamp)
                                                        FROM hit h3
                                                        WHERE h3.user_id = h1.user_id
                                                              AND h3.timestamp < h1.timestamp)
                LEFT JOIN hit h4
                          ON h4.user_id = h1.user_id
                             AND h4.timestamp = (SELECT min(h5.timestamp)
                                                        FROM hit h5
                                                        WHERE h5.user_id = h1.user_id
                                                              AND h5.timestamp > h1.timestamp)
    )
    SELECT c1.user_id,
           c1.page,
           c1.timestamp,
           concat((SELECT concat(c2.user_id, '-', to_char(max(c2.timestamp), 'YYYYMMDDHH24MI'))
                          FROM cte c2
                          WHERE c2.user_id = c1.user_id
                                AND c2.timestamp <= c1.timestamp
                                AND NOT c2.shares_session_with_previous
                          GROUP BY c2.user_id),
                  (SELECT to_char(min(c2.timestamp), 'HH24MI')
                          FROM cte c2
                          WHERE c2.user_id = c1.user_id
                                AND c2.timestamp >= c1.timestamp
                                AND NOT c2.shares_session_with_next)) session_id
           FROM cte c1
           ORDER BY c1.timestamp;
    

    核心部分是 CTE。对于每一行,具有最年轻的较早时间戳的行和具有最老的较年轻时间戳的行被连接。旧时间戳或最新时间戳与行的时间戳之间的间隔被检查为小于或等于 3600 秒。检查的结果存储在标志 shares_session_with_previousshares_session_with_next 中。

    然后使用这些标志来获取会话的开始和结束。开始是比shares_session_with_previousfalse 的当前时间戳早或等于当前时间戳的最年轻的时间戳。结束是比shares_session_with_nextfalse 的当前时间戳更早或等于当前时间戳的最早时间戳。

    将会话开始和结束的相应值连接起来以提供您的会话 ID。

    SQL Fiddle

    【讨论】:

      猜你喜欢
      • 2012-03-03
      • 2020-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-21
      • 2019-12-22
      • 1970-01-01
      • 2019-06-16
      相关资源
      最近更新 更多