-1

我有两个表,一个表是带有收入、purchase_time 和用户 ID 的购买列表,另一个表是带有活动 ID、用户 ID、click_time 的广告系列点击列表。campaign_clicks 基本上记录了一个广告系列的所有点击,可以有任意数量的点击或没有点击,这些可能在购买之前或之后的任何时间发生,但我需要做的是确定哪个campaign_id 是在购买之前被点击的最后一个广告系列由任何给定用户制作,以及归因于该campaign_id 的总收入是多少。我只想将收入归因于购买前 3 天内发生的点击。

购买

日期 用户身份 收入 购买时间
2020/09/01 10 30.0 2020/09/01 上午 10:10:00
2020/09/01 20 15.0 2020/09/02 上午 9:15:00
2020/09/01 30 25.0 2020/09/02 08:15:00 上午

广告系列点击次数

用户身份 广告系列_id 点击时间
10 2 2020/09/01 上午 10:01:00
10 1 2020/09/01 上午 10:05:00
10 2 2020/09/01 上午 10:20:00
20 2 2020/09/01 上午 10:10:00
30 2 2020/09/01 07:30:00 上午

期望的结果

日期 广告系列_id 收入
2020/09/01 1 30.0
2020/09/01 2 25.0

不应包括从用户 id 20 购买,因为它发生在 click_time 之前。用户 10 的收入应归因于广告系列 2,因为点击发生在购买之前。

我的问题是我的加入正在返回所有增加收入的点击。内部连接中的选择不知道购买时间,我需要以某种方式过滤并将点击缩小到单击,最后一次点击。我尝试使用 ROW_NUMBER() 应用索引,但这不允许我过滤掉购买后发生的点击。

这就是我所在的地方

SELECT  
  date
  ,ROUND(sum(revenue)) as revenue
  ,campaign_clicks.campaign_id
FROM 
    purchases                    
       
        LEFT JOIN ( 

                   SELECT                                   
                        campaign_id 
                        ,user_id
                        ,click_time                       
                   FROM 
                      campaign_clicks            
                   ORDER BY         
                      click_time DESC                             
                  ) AS clicks ON clicks.user_id = purchases.user_id 
WHERE 
  -- only select campaign clicks that occurred before the purchase                
  purchases.purchase_time > clicks.click_time

  -- only include clicks that occurred within 3 days of the purchase               
  AND DATEDIFF(minutes, clicks.click_time,purchases.purchase_time) <= (60*24*3)

  -- PROBLEM HERE - there can be still a number of other clicks that occurred before the purchase I need to filter to only the last one 
GROUP BY 
   date
 ,clicks.campaign_id
4

2 回答 2

1

那么您可以使用以下查询来实现这一点。因此,基本上,您可以执行 a并过滤掉子句本身INNER JOIN中持续时间超过 3 天的日期。ON

现在限制到最后点击的广告系列,可以使用ROW_NUMBER函数并将序列顺序设置为 来实现clicked_time DESC。这样,购买前的最后点击日期将有一个序列号。1。然后,您可以通过将结果集包装在外部查询中来过滤掉 row_number 大于 1 的记录。

-- Outer query to select just the last click for a any given purchase
SELECT * FROM (
    SELECT p.date, p.purchase_time, c.click_time, c.campaign_id, p.revenue,
-- sequential row number for clicks sorted in descending order of date
    ROW_NUMBER() OVER(PARTITION BY c.user_id ORDER BY c.click_time DESC) AS row_num
    FROM purchases p
    INNER JOIN campaign_clicks c
    ON ( 
       c.user_id = p.user_id 
      --- only select clicks that occured before the purchase
      AND c.click_time<p.purchase_time
      --- only select the clicks that occurred 3 days prior (mins * hours * days )
      AND TIMESTAMPDIFF(MINUTE, c.click_time, p.purchase_time) <= (60*24*3)
    )
) res WHERE res.row_num=1
您还可以在DB-Fiddle链接上查看结果
于 2021-09-28T04:51:55.620 回答
0

雪花支持横向连接。也就是说,转到函数或相关子查询。这允许您加入只返回一行(每个输入行)的查询。

SELECT  
  purchases.date
 ,purchases.revenue
 ,clicks.campaign_id
FROM 
  purchases    
LEFT JOIN LATERAL
(
  SELECT
    campaign_id 
   ,user_id
   ,click_time                       
  FROM 
    campaign_clicks
  WHERE
            user_id = purchases.user_id
    -- only select campaign clicks that occurred before the purchase                
    AND click_time <  purchases.purchase_time
    -- only include clicks that occurred within 3 days of the purchase               
    AND click_time >= DATEADD(days, -3, purchases.purchase_time)
  ORDER BY
    click_time DESC
  LIMIT
    1                        
)
  AS clicks
于 2021-09-28T05:09:25.110 回答