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 查询。
如果满足以下任一条件,则点击被视为新会话的开始:
- 这是其 userId 的第一个点击
- 上一次点击的时间戳与
同一个userId超过30分钟
- 同一个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
希望对您有所帮助
我有一个包含 4 列的 table:hitId、userId、timestamp 和 Camp。 我需要使用两个参数对点击是否是新会话的开始(1 或 0)进行分类:1.点击之间的时间差和 2.如果点击的来源是新活动。
我需要 BigQuery 中的标准 SQL 查询。
如果满足以下任一条件,则点击被视为新会话的开始:
- 这是其 userId 的第一个点击
- 上一次点击的时间戳与 同一个userId超过30分钟
- 同一个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
希望对您有所帮助