Bigquery Rolling month data

Viewed 876

I'm trying to achieve output like this.How many times user visited particular page in 3 months. Pages are like Homepage,acountpage,cartpage etc.

My table

MMDDYY  Pagevisted  Username    No. of time Month
1/1/2019    Homepage    A   1   January
2/21/2019   AccountPage A       1   February
2/25/2019   AccountPage B   5   February
3/1/2019    Homepage    A   3   March
4/2/2019    cartpage            B   2   April
5/2/2019    AccountPage A   1   May
6/2/2019    Submisison  C   1   June
5/5/2019    Homepage    D   2   May
5/2/2019    Articles    E   2   May
7/25/2019   cartpage            E   2   July
8/12/2019   Articles    A   1   August
9/23/2019   Articles    A       6   September

Please can you help me with the query to fetch the data in Rolling-based method. E.g. If Current month is January, I need data for Jan,Feb and March If current month is February, I need data for Feb,March,April If current month is March, I need data for March,April,May and so on.

Output should be :

MMDDYY  Pagevisted  Username    No. of time[3 M rolling month]  
1/1/2019    Homepage    A   4   this include 1 from jan, 3 from march
2/21/2019   AccountPage A   1   Account page opened by A user from current month to next other 2 month i.e. Mar April is only once
2/25/2019   AccountPage B   5   Account page opened by B user from current month to next other 2 month i.e. Mar April is only 5 time
3/1/2019    Homepage    A   3   User A in march month opened homepage 3 time, but he didn't opened in following 2 other month i.e. Mar April May
6/2/2019    Submisison  C   1   
5/5/2019    Homepage    D   2   
5/2/2019    Articles    E   2   
7/25/2019   cartpage            E   2   
8/12/2019   Articles    A   7   
9/23/2019   Articles    A       6   
2 Answers

Below is for BigQuery Standard SQL

#standardSQL
SELECT *, SUM(no_of_time) OVER(rolling_3_month_window) AS rolling_3_month
FROM `project.dataset.table`
WINDOW rolling_3_month_window AS (    
  PARTITION BY username, pagevisited 
  ORDER BY DATE_DIFF(PARSE_DATE('%m/%d/%Y', mmddyyyy), '1970-01-01', MONTH)
  RANGE BETWEEN CURRENT ROW AND 2 FOLLOWING 
)

If to apply to sample data from your question as in below example

#standardSQL
WITH `project.dataset.table` AS (
  SELECT '1/1/2019' mmddyyyy, 'Homepage' pagevisited, 'A' username, 1 no_of_time, 'January' month UNION ALL
  SELECT '2/21/2019', 'AccountPage', 'A', 1, 'February' UNION ALL
  SELECT '2/25/2019', 'AccountPage', 'B', 5, 'February' UNION ALL
  SELECT '3/1/2019', 'Homepage', 'A', 3, 'March' UNION ALL
  SELECT '4/2/2019', 'cartpage', 'B', 2, 'April' UNION ALL
  SELECT '5/2/2019', 'AccountPage', 'A', 1, 'May' UNION ALL
  SELECT '6/2/2019', 'Submisison', 'C', 1, 'June' UNION ALL
  SELECT '5/5/2019', 'Homepage', 'D', 2, 'May' UNION ALL
  SELECT '5/2/2019', 'Articles', 'E', 2, 'May' UNION ALL
  SELECT '7/25/2019', 'cartpage', 'E', 2, 'July' UNION ALL
  SELECT '8/12/2019', 'Articles', 'A', 1, 'August' UNION ALL
  SELECT '9/23/2019', 'Articles', 'A', 6, 'September' 
)
SELECT *, SUM(no_of_time) OVER(rolling_3_month_window) AS rolling_3_month
FROM `project.dataset.table`
WINDOW rolling_3_month_window AS (    
  PARTITION BY username, pagevisited 
  ORDER BY DATE_DIFF(PARSE_DATE('%m/%d/%Y', mmddyyyy), '1970-01-01', MONTH)
  RANGE BETWEEN CURRENT ROW AND 2 FOLLOWING 
)
-- ORDER BY mmddyyyy    

output is

Row mmddyyyy    pagevisited username    no_of_time  month       rolling_3_month  
1   1/1/2019    Homepage    A           1           January     4    
2   2/21/2019   AccountPage A           1           February    1    
3   2/25/2019   AccountPage B           5           February    5    
4   3/1/2019    Homepage    A           3           March       3    
5   4/2/2019    cartpage    B           2           April       2    
6   5/2/2019    AccountPage A           1           May         1    
7   5/2/2019    Articles    E           2           May         2    
8   5/5/2019    Homepage    D           2           May         2    
9   6/2/2019    Submisison  C           1           June        1    
10  7/25/2019   cartpage    E           2           July        2    
11  8/12/2019   Articles    A           1           August      7    
12  9/23/2019   Articles    A           6           September   6    

You seem to want count(*) with a window frame:

select t.*,
       sum(num_times) over (partition by username, pagevisited
                            order by extract(year from date) * 12 + extract(month from date)
                            range between 2 preceding and current row
                           )
from t;

This assumes that your date column is actually a date -- which is the right way to store such a value. If not, you can convert it.

Related