2017-04-14 76 views
3

我正在試圖計算每個月沒有出現在上個月的唯一用戶。所以如果用戶有1月份的記錄,2月份的記錄是2月份的記錄,那麼我只計算該用戶的1月份。如何計算一個月內未出現在前一個月的用戶?

user_id time 
a1   1/2/17 
a1   2/10/17 
a2   2/18/17 
a4   2/5/17 
a5   3/25/17 

我的結果應該是這樣的

Month User Count 
January  1 
February 2 
March  1 
+0

「所以,如果一個用戶有一月二月的紀錄,然後又一個,那麼我只會計算該用戶的一月份。「你的意思是你只計算二月? – CodingYoshi

+0

他只想算第一次...... – Teja

回答

0

用戶ID和每月第一聚集。然後使用lag(),看看用戶是否存在於前一個月:

with du as (
     select date_trunc(time, month) as yyyymm, user_id 
     from t 
     group by date_trunc(time, month) 
    ) 
select yyyymm, count(*) 
from (select du.*, 
      lag(yyyymm) over (partition by user_id order by yyyymm) as prev_yyyymm 
     from du 
    ) du 
where prev_yyyymm is not null or 
     prev_yyyymm < date_add(yyyymm, interval 1 month) 
group by yyyymm; 

注:本品採用date功能,但對於timestamp存在類似的功能。

0

我理解問題的方式是 - 僅當用戶在前一個月出現過的情況下,才排除用戶在給定月份進行計數。但是,如果同一用戶在給定之前的幾個月內出席,但以前沒有 - 用戶應計算在內。

如果這是正確的 - 下面嘗試使用BigQuery的標準SQL

#standardSQL 
SELECT Year, Month, COUNT(DISTINCT user_id) AS User_Count 
FROM (
    SELECT *, 
    DATE_DIFF(time, LAG(time) OVER(PARTITION BY user_id ORDER BY time), MONTH) AS flag 
    FROM (
    SELECT 
     user_id, 
     DATE_TRUNC(PARSE_DATE('%x', time), MONTH) AS time, 
     EXTRACT(YEAR FROM PARSE_DATE('%x', time)) AS Year, 
     FORMAT_DATE('%B', PARSE_DATE('%x', time)) AS Month 
    FROM yourTable 
    GROUP BY 1, 2, 3, 4 
) 
) 
WHERE IFNULL(flag, 0) <> 1 
GROUP BY Year, Month, time 
ORDER BY time 

您可以測試/上面使用例如虛擬數據低於從你的問題

#standardSQL 
WITH yourTable AS (
    SELECT 'a1' AS user_id, '1/2/17' AS time UNION ALL 
    SELECT 'a1', '2/10/17' UNION ALL 
    SELECT 'a2', '2/18/17' UNION ALL 
    SELECT 'a4', '2/5/17' UNION ALL 
    SELECT 'a5', '3/25/17' 
) 
SELECT Year, Month, COUNT(DISTINCT user_id) AS User_Count 
FROM (
    SELECT *, 
    DATE_DIFF(time, LAG(time) OVER(PARTITION BY user_id ORDER BY time), MONTH) AS flag 
    FROM (
    SELECT 
     user_id, 
     DATE_TRUNC(PARSE_DATE('%x', time), MONTH) AS time, 
     EXTRACT(YEAR FROM PARSE_DATE('%x', time)) AS Year, 
     FORMAT_DATE('%B', PARSE_DATE('%x', time)) AS Month 
    FROM yourTable 
    GROUP BY 1, 2, 3, 4 
) 
) 
WHERE IFNULL(flag, 0) <> 1 
GROUP BY Year, Month, time 
ORDER BY time 

輸出是玩

Year Month  User_Count 
2017 January  1  
2017 February 2  
2017 March  1  
+0

我不認爲這是OP想要的。基本上希望在第一次出現在一個月內計算用戶,並且不再計算一次。 – CodingYoshi

+0

在下面的語句'上個月沒有出現''''單注'月份'。不是'月',而是'月'。無論如何 - 讓我們把它留給OP來澄清! :o) –

+0

同意讓我們這樣做。不知道爲什麼我提供我的2美分,甚至不富裕;) – CodingYoshi

1

我不是真的家人用BigQuery騙子,但這裏是我如何使用TSQL解決問題。我想你可以在BigQuery中使用類似的邏輯。

1)。先按user_id排序,然後按時間排序。在TSQL中,可以使用以下代碼完成此操作,並將其存儲在公用表表達式中,然後在此步驟中查詢。

;WITH cte AS 
(
select ROW_NUMBER() OVER (PARTITION BY [user_id] ORDER BY [time]) AS rn,* 
from dbo.employees 
) 

2)。接下來只查詢rn = 1的行(特定用戶的第一次出現)和月份的組。

select DATENAME(month, [time]) AS [Month], count(*) AS user_count 
from  cte 
where  rn = 1  
group by DATENAME(month, [time]) 

這是假設2017年是你處理的唯一一年。如果您正在處理超過一年,你可能想步驟#2是這個樣子:

select year([time]) as [year], DATENAME(month, [time]) AS [month], 
      count(*) AS user_count 
from  cte 
where  rn = 1  
group by year([time]), DATENAME(month, [time])