Sql 谷歌大查询排名顺序与客户点击问题

Sql 谷歌大查询排名顺序与客户点击问题,sql,google-bigquery,ranking,Sql,Google Bigquery,Ranking,我正在使用google big query跟踪一些客户对我网站的点击。我遵循一个简单的规则集: 如果客户在同一天连续多次通过同一来源,我只想看到第一个命中来源 我只想看到第一个击中来源,如果客户已经通过同一来源多次连续在不同的日子 我希望看到所有命中源,如果它们出现在同一天,但不是连续出现 目前,我正在使用以下工具: rank() over (partition by customer_code, hit_source order by hit_timedate) rnk 如果我在“wh

我正在使用google big query跟踪一些客户对我网站的点击。我遵循一个简单的规则集:

  • 如果客户在同一天连续多次通过同一来源,我只想看到第一个命中来源

  • 我只想看到第一个击中来源,如果客户已经通过同一来源多次连续在不同的日子

  • 我希望看到所有命中源,如果它们出现在同一天,但不是连续出现

  • 目前,我正在使用以下工具:

    rank() over (partition by customer_code, hit_source order by hit_timedate) rnk
    
    如果我在“where rnk=1”上过滤,这允许我完成前两个步骤。这只会给我不同的命中源,无论它们是否在同一天,因为我有一个在命中时间内的时间。但它并没有给我第三步,因为排名是由hit_源划分的,当它看到相同的源时会改变

    如果有人能在这方面帮助我,我将不胜感激

    编辑:

    不确定如何添加/上载示例数据集,因此我尝试在此处执行此操作:

    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”的点击不是连续的。但要用我实现的前两条规则做到这一点,我很难做到。

    您可以使用
    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

    开始,以便进一步为社区做出贡献,我将使用不同的方法与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
    
    和最终输出,

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


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

    请提供示例数据和所需结果。正如@GordonLinoff所说,你能分享一下样本数据和预期结果吗?所以,最好创建一个查询并对其进行测试。您好,示例和所需结果集作为一个版本添加到我的原始帖子中。谢谢。@DB1993,为什么Facebook在2020年5月25日13:00pm排名1而不是4?你好,Alexandre,这是因为Facebook的第4行不是连续的,因为之前有不同的点击源,所以它会重置回排名1,这是我计划实现的逻辑。我希望你能理解您好,根据我的原始问题,这与我期望的结果集不匹配。请特别注意所需的结果集“排名”。Facebook的第一个和第四个实例应该是排名1,因为之前的热门来源不是Facebook。@db1993,您好,谢谢您让我知道。因此,我们的想法是,在我们有了一个允许我们对连续动作进行分组的专栏之后,就有可能进行排名。因此,您只需在代码的最后一部分中使用RANK()函数。我已经上传了新的代码和输出。你检查过了吗?请考虑投票和接受答案。@ DbBDB1993,请考虑接受和投票的答案。您好,使用亚历山大的例子,他的CTE手动插入数据集。这似乎给了我每行3的排名。我需要有我在期望的结果集中指定的排名。这样我就可以过滤排名=1的位置等@db1993。
    countif()
    需要一个
    orderby
    子句。
    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
    
    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