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

时间:2018-12-12 20:41:26

标签: sql session google-bigquery partitioning

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

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

如果满足以下条件之一,则将匹配视为新会话的开始:

  1. 这是其userId的第一个匹配项
  2. 上次匹配的时间戳记之间的时间差 相同的userId超过30分钟。
  3. 来自同一userId的上一个匹配的时间戳之间的时间差小于30分钟,但是Camp(广告系列)值不是NULL,并且是在前30分钟内首次出现于同一userId的时间。 / li>

因此,如果用户1的hit1的Camp等于Campaign1,用户1的hit2的Camp等于Campaign1,并且hit1和hit2之间的时间差小于30分钟,则hit1将被视为会话的开始,并且hit2不会被视为一个开始。

我在Campaign部分遇到了麻烦。我尝试了这段代码:

我尝试了以下代码:

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)似乎不起作用:

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

1 个答案:

答案 0 :(得分:0)

在用户具有多个Camp的情况下,此RANK()OVER(PARTITION BY userId或ORDER BY Camp)返回错误的结果。

请注意,当您要标记每个Camp中的会话时,您的PARTITION BY使用userId。

userId 00150的RANK()(...)语句的实际“等级1”是Camp为NULL(hitId 00150)的位置,因此它缺少您在hitId 00152的CASE条件。

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

或者,您可以替换RANK()(...)并使用LAG(Camp)(...按时间戳排序),而不要计算LAG(timestamp)(...)。 这将检索之前行的Camp值(称为“ PreviousCampValue”)。然后,您可以添加类似WHEN PreviousCampValue!= Camp THEN 1

希望有帮助