TSQL时间序列模式数据挖掘

时间:2011-04-21 11:31:53

标签: sql-server tsql

使用以下3个字段获取SQL表:

Id,TimeStamp,Item,UserId

我想确定会话中Item的最常见UserId序列。会话将简单地由时间阈值定义(即,如果X分钟没有进入,则将来的任何条目将被分组到新会话中。)

理想情况下,项目序列可以有一种模糊分组,其中序列中的一个或两个差异仍然可以计算为相同并组合在一起。

任何人都知道如何在SQL中解决这个问题?

更新
为了澄清,让我们假装这些物品是杂货店的岛屿。我有一个月的人去杂货店。基本问题是人们使用的是什么,它是什么顺序。他们最常去岛屿1,2,31,2,1,3,4吗?

(现在我对我们网站上的用户路径很好奇,但是你知道,杂货店更直观)。

更新2:
这是一个简单的案例:

CREATE Table #StoreActivity
(
    id int,
    CreationDate datetime ,
    Isle int,
    UserId int
)

Insert INTO #StoreActivity
Values
    (1, CAST('12-1-2011 03:10:01' AS Datetime), 1, 2222),
    (2, CAST('12-1-2011 03:10:07' AS Datetime), 1, 1111),
    (3, CAST('12-1-2011 03:10:12' AS Datetime), 2, 2222),
    (4, CAST('12-1-2011 04:10:01' AS Datetime), 1, 2222),
    (5, CAST('12-1-2011 04:10:23' AS Datetime), 2, 2222)

Select * from #StoreActivity
DROP Table #StoreActivity

/* So with the above data, we have 2 sequences if we declare a session or visit dead if there is no activity for a minute : `1,2` (With a count of 2), and `1` (with a count of 1)*/

2 个答案:

答案 0 :(得分:1)

WITH    q AS
        (
        SELECT  *,
                ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY TimeStamp, Id) AS rn,
                ROW_NUMBER() OVER (PARTITION BY UserId, Item ORDER BY TimeStamp, Id) AS rnd
        FROM    mytable
        )
SELECT  *,
        rnd - rn AS sequence
FROM    q

sequence列将在给定UserId的序列中的所有记录之间共享。你可以分组或做任何你喜欢的事情。

答案 1 :(得分:0)

这听起来像旧时尚协会规则挖掘问题(但是订购使其变得更容易),如果我理解了正确的问题,那么这个问题没有一个[EFFICIENT] SQL答案。

  • 如果您的问题涉及最大频繁的路线挖掘(例如路线1,3,2可以在路线4,1,3,2和1,3,2,4中使用),那么它将不会这么容易解决。我建议在SSAS数据挖掘中查看AR挖掘。

  • 如果您的问题不涉及最大频繁的路由挖掘(例如,只有当它使用完全相同的路线时才会计算1,3,2)那么这只是分组依据和计数的问题。

在您能够使用上述任何解决方案之前,您需要找出可以使用以下脚本完成的会话:

WITH ts as
(
    SELECT 
        id,
        UserId, 
        CreationDate,
        Isle,
        ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY CreationDate) AS rowNum
    FROM #StoreActivity a

)
SELECT t2.*, KeepSession = CASE WHEN DATEDIFF(second,t1.CreationDate, t2.CreationDate) > 60 THEN 0 ELSE 1 END   
INTO #tempStore
FROM ts as t1
LEFT JOIN ts as t2 ON t1.rowNum = t2.rowNum - 1 
WHERE t1.UserId = t2.UserId

SELECT *, id, UserId, 
SessionId = (SELECT count(*) FROM #tempStore where KeepSession = 0 and UserId = t.UserId and rowNum <= t.rowNum)
FROM #tempStore t
--where t. t.KeepSession = 0

DROP TABLE #tempStore

结果将是:

id          UserId      CreationDate            Isle        rowNum               KeepSession id          UserId      SessionId
----------- ----------- ----------------------- ----------- -------------------- ----------- ----------- ----------- -----------
3           2222        2011-12-01 03:10:12.000 2           2                    1           3           2222        0
4           2222        2011-12-01 04:10:01.000 1           3                    0           4           2222        1
5           2222        2011-12-01 04:10:23.000 2           4                    1           5           2222        1
6           2222        2011-12-01 04:10:24.000 3           5                    1           6           2222        1
7           2222        2011-12-01 04:12:23.000 3           6                    0           7           2222        2
8           2222        2011-12-01 04:12:24.000 3           7                    1           8           2222        2

(6 row(s) affected)

注意:上述解决方案可针对性能进行优化。 #tempStore可以删除。