2017-05-31 71 views
1

我有時間的訪問,時間戳記這樣如何查找連續日期的最長序列?

ID, time 
1, 1493596800 
1, 1493596900 
1, 1493432800 
2, 1493596800 
2, 1493596850 
2, 1493432800 

我用火花SQL數據庫,我需要有像

ID, longest_seq (days) 
1, 2 
2, 5 
3, 1 

每個ID consecutives的最長序列中的日期我試着去適應這個回答Detect consecutive dates ranges using SQL對我來說,但我沒有達到我的期望。

SELECT ID, MIN (d), MAX(d) 
    FROM (
     SELECT ID, cast(from_utc_timestamp(cast(time as timestamp), 'CEST') as date) AS d, 
       ROW_NUMBER() OVER(
     PARTITION BY ID ORDER BY cast(from_utc_timestamp(cast(time as timestamp), 'CEST') 
                  as date)) rn 
     FROM purchase 
     where ID is not null 
     GROUP BY ID, cast(from_utc_timestamp(cast(time as timestamp), 'CEST') as date) 
    ) 
    GROUP BY ID, rn 
    ORDER BY ID 

如果有人對如何解決這一要求,或有什麼錯在它的一些線索,我將不勝感激幫助 感謝

[編輯]一個更明確的輸入/輸出

ID, time 
1, 1 
1, 2 
1, 3 
2, 1 
2, 3 
2, 4 
2, 5 
2, 10 
2, 11 
3, 1 
3, 4 
3, 9 
3, 11 

其結果將是:

ID, MaxSeq (in days) 
1,3 
2,3 
3,1 

所有的訪問是在時間戳,但我需要連續幾天,然後每天每次訪問一天一次地計算在內

+0

你能給出更具代表性的意見嗎?我認爲輸入數據集不匹配結果。 –

回答

0

這就是我喜歡的窗口集合函數的情況!

我想下面的例子可以幫助你(至少開始)。

以下是我使用的數據集。我將您的時間(長時間)轉換爲數字時間來表示一天(並避免在Spark SQL中使用時間戳,這可能會使解決方案難以理解...... 可能)。

scala> visits.show 
+---+----+ 
| ID|time| 
+---+----+ 
| 1| 1| 
| 1| 1| 
| 1| 2| 
| 1| 3| 
| 1| 3| 
| 1| 3| 
| 2| 1| 
| 3| 1| 
| 3| 2| 
| 3| 2| 
+---+----+ 

讓我們定義窗口規範,將id行分組在一起。

import org.apache.spark.sql.expressions.Window 
val idsSortedByTime = Window. 
    partitionBy("id"). 
    orderBy("time") 

用那個你rank行和具有相同等級的計數行。

val answer = visits. 
    select($"id", $"time", rank over idsSortedByTime as "rank"). 
    groupBy("id", "time", "rank"). 
    agg(count("*") as "count") 
scala> answer.show 
+---+----+----+-----+ 
| id|time|rank|count| 
+---+----+----+-----+ 
| 1| 1| 1| 2| 
| 1| 2| 3| 1| 
| 1| 3| 4| 3| 
| 3| 1| 1| 1| 
| 3| 2| 2| 2| 
| 2| 1| 1| 1| 
+---+----+----+-----+ 

出現(非常接近?)解決方案。 你似乎完成了!

+0

感謝您的幫助 我不確定按ID,時間和等級計數的使用情況,它代表按ID編號的訪問次數,日期?那麼爲什麼我們應該使用排名功能呢? – Farah

1

我在下面的答案是從https://dzone.com/articles/how-to-find-the-longest-consecutive-series-of-even改編的,用於Spark SQL。你必須與包裹SQL查詢:

spark.sql(""" 
SQL_QUERY 
""") 

因此,對於第一個查詢:

CREATE TABLE intermediate_1 AS 
SELECT 
    id, 
    time, 
    ROW_NUMBER() OVER (PARTITION BY id ORDER BY time) AS rn, 
    time - ROW_NUMBER() OVER (PARTITION BY id ORDER BY time) AS grp 
FROM purchase 

這會給你:

id, time, rn, grp 
1, 1, 1, 0 
1, 2, 2, 0 
1, 3, 3, 0 
2, 1, 1, 0 
2, 3, 2, 1 
2, 4, 3, 1 
2, 5, 4, 1 
2, 10, 5, 5 
2, 11, 6, 5 
3, 1, 1, 0 
3, 4, 2, 2 
3, 9, 3, 6 
3, 11, 4, 7 

我們可以看到,連續行具有相同的grp值。然後我們將使用GROUP BY和COUNT來獲取連續時間的數量。

CREATE TABLE intermediate_2 AS 
SELECT 
    id, 
    grp, 
    COUNT(*) AS num_consecutive 
FROM intermediate_1 
GROUP BY id, grp 

這將返回:

id, grp, num_consecutive 
1, 0, 3 
2, 0, 1 
2, 1, 3 
2, 5, 2 
3, 0, 1 
3, 2, 1 
3, 6, 1 
3, 7, 1 

現在我們只是使用MAX和GROUP BY獲得的連續時間的最大數量。

CREATE TABLE final AS 
SELECT 
    id, 
    MAX(num_consecutive) as max_consecutive 
FROM intermediate_2 
GROUP BY id 

,這將給你:

id, max_consecutive 
1, 3 
2, 3 
3, 1 

希望這有助於!