【问题标题】:Google big query ranking order with customer hits problem有客户点击问题的谷歌大查询排名顺序
【发布时间】:2020-07-02 15:08:46
【问题描述】:

我正在使用谷歌大查询来跟踪一些客户点击我的网站。我遵循一个简单的规则集:

  1. 如果客户在同一天连续多次访问同一来源,我只想查看第一个命中来源。

  2. 如果客户在不同的日子连续多次访问同一来源,我只想查看第一个命中来源。

  3. 如果它们出现在同一天但不是连续出现,我想查看所有热门来源。

目前,我正在使用以下内容:

rank() over (partition by customer_code, hit_source order by hit_timedate) rnk

如果我过滤“where rnk = 1”,这可以让我完成前两个步骤。这只会给我不同的命中来源,无论它们是否在同一天,因为我在 hit_timedate 中有时间。但它并没有给我第三步,因为排名是由 hit_source 划分的,当它看到相同的源时会改变。

如果有人可以帮助我,将不胜感激。

编辑:

不确定如何添加/上传示例数据集,所以我在这里尝试过:

Customer_Code       Hit_Source               Hit_Timedate
     101             Facebook             25/05/2020 10:30am
     101             Facebook             25/05/2020 11:45am
     101             Facebook             25/05/2020 11:55am
     101             Twitter              25/05/2020 12:30am
     101             Facebook             25/05/2020 13:00pm 
     101             Google               25/05/2020 15:00pm
     101             Instagram            26/05/2020 09:00am

理想的结果集应该是这样的:

Customer_Code       Hit_Source               Hit_Timedate        Rank
     101             Facebook             25/05/2020 10:30am       1
     101             Facebook             25/05/2020 11:45am       2
     101             Facebook             25/05/2020 11:55am       3
     101             Twitter              25/05/2020 12:30am       1
     101             Facebook             25/05/2020 13:00pm       1
     101             Google               25/05/2020 15:00pm       1
     101             Instagram            26/05/2020 09:00am       1

所以,根据我想在上面实施的规则.. 我在这里遇到的主要问题是能够将样本中的第 5 行列为“1”。我想这样做是因为最后两个“Facebook”点击不是连续的。但是能够使用我实施的前 2 条规则来做到这一点,我正在苦苦挣扎。

【问题讨论】:

  • 请提供样本数据和期望的结果。
  • 正如@GordonLinoff 所说,您能否分享示例数据和预期结果?因此,最好创建一个查询并对其进行测试。
  • 您好,示例和所需结果集已作为版本添加到我的原始帖子中。谢谢。
  • @dbdbdb1993,为什么 Facebook 在 25/05/2020 下午 13:00 排名 1 而不是 4?
  • 你好 Alexandre,这是因为 facebook 的第 4 行不是连续的,因为之前有不同的 hit_sources 所以它会重置回 1 级,这是我计划实现的逻辑。希望你能理解

标签: sql google-bigquery ranking


【解决方案1】:

您可以使用lag() 和累积计数:

select t.*,
       1 + countif(prev_source = source) over (partition by customer_code, datetime_trunc(hit_timedate, day) order by hit_timedate) as ranking
from (select t.*,
             lag(source) over (partition by customer_code, datetime_trunc(hit_timedate, day)
                               order by hit_timedate
                              ) as prev_source
     from t
    ) t;

这个想法是创建一个标志,以判断前一个源是否与当前行相同——如果不是,则加 1。1 + 是因为计数将从 0 开始,而你希望计数从 1 开始。

【讨论】:

  • 您好,使用 Alexandres 的 CTE 示例手动插入数据集。这似乎给了我每行 3 的排名。我需要按照我在所需结果集中指定的排名。这样我可以过滤排名 = 1 等的位置。
  • @dbdbdb1993 。 . . countif() 需要一个 order by 子句。
【解决方案2】:

为了进一步为社区做出贡献,我将分享使用 LAG()SUM()CASE WHENMIN() BigQuery 内置函数的不同方法。

以下是您提供的示例数据,分为 2 个步骤(在其中注释):

with data as (
SELECT 101 as Customer_Code,"Facebook" as Hit_Source ,DATETIME(2020,05,25,10,30,00) as Hit_Timedate UNION ALL
SELECT 101 as Customer_Code,"Facebook" as Hit_Source ,DATETIME(2020,05,25,11,45,0) as Hit_Timedate UNION ALL
SELECT 101 as Customer_Code,"Facebook" as Hit_Source ,DATETIME(2020,05,25,11,55,0) as Hit_Timedate UNION ALL
SELECT 101 as Customer_Code,"Twitter" as Hit_Source ,DATETIME(2020,05,25,12,30,0) as Hit_Timedate UNION ALL
SELECT 101 as Customer_Code,"Facebook" as Hit_Source ,DATETIME(2020,05,25,13,00,0) as Hit_Timedate UNION ALL
SELECT 101 as Customer_Code,"Google" as Hit_Source ,DATETIME(2020,05,25,15,00,0) as Hit_Timedate UNION ALL
SELECT 101 as Customer_Code,"Instagram" as Hit_Source ,DATETIME(2020,05,25,09,00,0) as Hit_Timedate 
),
#step 1
data1 as (
SELECT Customer_Code, Hit_Source, Hit_Timedate, LAG(Hit_Source,1) OVER (ORDER BY Hit_Timedate) as PrevHit from data
),
#step 2
data2 as (
SELECT Customer_Code, Hit_Source,PrevHit , Hit_Timedate, SUM(CASE WHEN Hit_Source = PrevHit THEN 0 ELSE 1 END) OVER (ORDER BY Hit_Timedate,Hit_Source) AS rank_aux
FROM data1
)

SELECT Customer_Code, Hit_Source, MIN(Hit_Timedate) AS first_Hit_Timedate, RANK() OVER (PARTITION BY rank_aux order by Hit_Timedate) as rank FROM data2 
GROUP BY Customer_Code, Hit_Source, rank_aux,Hit_Timedate
ORDER BY Customer_Code,first_Hit_Timedate, Hit_Source

最后的输出,

Row Customer_Code   Hit_Source  first_Hit_Timedate  rank
1   101             Instagram   2020-05-25T09:00:00 1
2   101             Facebook    2020-05-25T10:30:00 1
3   101             Facebook    2020-05-25T11:45:00 2
4   101             Facebook    2020-05-25T11:55:00 3
5   101             Twitter     2020-05-25T12:30:00 1
6   101             Facebook    2020-05-25T13:00:00 1
7   101             Google      2020-05-25T15:00:00 1

请注意,在第 1 步中,会创建一个新列,其中包含 Hit_Source 的先前值。然后在第 2 步中,创建一个新列 rank_aux 以便正确聚合结果。以下是步骤 2 的输出(仅用于解释目的):

Row Customer_Code   Hit_Source  PrevHit     Hit_Timedate        rank_aux
1   101             Instagram   null        2020-05-25T09:00:00 1
2   101             Facebook    Instagram   2020-05-25T10:30:00 2
3   101             Facebook    Facebook    2020-05-25T11:45:00 2
4   101             Facebook    Facebook    2020-05-25T11:55:00 2
5   101             Twitter     Facebook    2020-05-25T12:30:00 3
6   101             Facebook    Twitter     2020-05-25T13:00:00 4
7   101             Google      Facebook    2020-05-25T15:00:00 5

注意rank_aux=2 所在的第 2、3 和 4 行,这是所需的输出,因此可以将这些列聚合为 1 并仅显示最小值 Hit_Timedate 以获得最终输出,已共享。

【讨论】:

  • 您好,根据我原来的问题,这与我想要的结果集不匹配。请特别注意所需的结果集“排名”。 Facebook 的第一个和第四个实例应该是排名 1,因为之前的点击源不是 Facebook。
  • @dbdbdb1993,您好,感谢您告诉我。所以想法是,在我们有一个允许我们对连续动作进行分组的列之后,就可以进行排名了。因此,您只需在代码的最后一部分中使用 RANK() 函数。我已经上传了新的代码和输出。你检查了吗?请考虑投票并接受答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-29
  • 1970-01-01
  • 1970-01-01
  • 2012-10-09
  • 1970-01-01
相关资源
最近更新 更多