PARTITION BY in CASE 不适用于多个 AND 语句

PARTITION BY in CASE doesn't work with several AND statements

我有一个包含 4 列的 table:hitId、userId、timestamp 和 Camp。 我需要使用两个参数对点击是否是新会话的开始(1 或 0)进行分类:1.点击之间的时间差和 2.如果点击的来源是新活动。

我需要 BigQuery 中的标准 SQL 查询。

如果满足以下任一条件,则点击被视为新会话的开始:

  1. 这是其 userId 的第一个点击
  2. 上一次点击的时间戳与 同一个userId超过30分钟
  3. 同一个userId上一次点击时间戳的时间差小于30分钟,但Camp(广告活动)值不为NULL,并且是前30分钟内第一次出现同一个userId .

所以如果来自user1的hit1有一个等于Campaign1的营地,并且来自user1的hit2有一个等于Campaign1的营地,并且hit1和hit2之间的时间差小于30分钟,hit1将被视为一个开始会话,hit2 不会被视为开始。

我在竞选部分遇到了问题。我试过这段代码:

我试过这段代码:

WITH timeDifference AS (
  SELECT *, 
  TIMESTAMP_DIFF(timestamp, LAG(timestamp, 1) OVER
          (PARTITION BY userId ORDER BY timestamp), SECOND) AS difference
    FROM hitTable
      ORDER BY timestamp)
SELECT *, 
  CASE 
  WHEN difference >= 30 * 60 THEN 1 
  WHEN difference IS NULL THEN 1 
  WHEN difference <= 30 * 60 AND Camp IS NOT NULL AND RANK() 
  OVER (PARTITION BY userId ORDER BY Camp) = 1 THEN 1
  ELSE 0 END AS sess
  FROM timeDifference
  ORDER BY timestamp;

条件 RANK() OVER (PARTITION BY userId ORDER BY Camp) 似乎不起作用,因为我收到此 table:

hitId | userId |  timestamp   |  Camp           |  difference  |  sess
_______________________________________________________________________
00150 | 858201 | 00:48:35.315 |  NULL           |  NULL        |  1
00151 | 858201 | 00:49:35.315 |  NULL           |  5           |  0
00152 | 858201 | 00:50:35.315 |  Search-Ads-US  |  10          |  0
00153 | 858201 | 00:53:35.315 |  Search-Ads-US  |  15          |  0
00154 | 858202 | 00:54:35.315 |  Facebook-Ads   |  NULL        |  1
00155 | 858202 | 00:54:55.315 |  Facebook-Ads   |  9           |  0
00156 | 858202 | 00:57:20.315 |  Facebook-Ads   |  12          |  0

虽然我希望 hitId = 00152 的 sess 列有 1 个:

hitId | userId |  timestamp   |  Camp           |  difference  |  sess
_______________________________________________________________________
00150 | 858201 | 00:48:35.315 |  NULL           |  NULL        |  1
00151 | 858201 | 00:49:35.315 |  NULL           |  5           |  0
00152 | 858201 | 00:50:35.315 |  Search-Ads-US  |  10          |  1
00153 | 858201 | 00:53:35.315 |  Search-Ads-US  |  15          |  0
00154 | 858202 | 00:54:35.315 |  Facebook-Ads   |  NULL        |  1
00155 | 858202 | 00:54:55.315 |  Facebook-Ads   |  9           |  0
00156 | 858202 | 00:57:20.315 |  Facebook-Ads   |  12          |  0

这个 RANK() OVER (PARTITION BY userId ORDER BY Camp) returns 在用户拥有多个营地的情况下会产生错误结果。

请注意您的 PARTITION BY 使用 userId,而您想要在每个训练营中标记会话。

用户 ID 00150 的 RANK() (...) 语句的实际 "rank 1" 是 Camp 为 NULL(hitId 00150)的地方,因此它错过了 hitId 00152 处的 CASE 条件。

您可以尝试将 'Camp' 添加到您的 PARTITION BY,如下所示: RANK() OVER (PARTITION BY userId, Camp ORDER BY Camp)

或者,除了您正在计算的 LAG(timestamp) (...) 之外,您还可以替换 RANK() (...) 并使用 LAG(Camp)(...按时间戳排序)。 这将检索之前行的 Camp 值(称之为 'PreviousCampValue')。然后你可以添加类似 WHEN PreviousCampValue != Camp THEN 1

希望对您有所帮助