Sql server 时间序列模式数据挖掘
以包含以下3个字段的SQL表为例:Sql server 时间序列模式数据挖掘,sql-server,tsql,Sql Server,Tsql,以包含以下3个字段的SQL表为例: Id,TimeStamp,Item,UserId 我想为会话中的用户id确定最常见的项序列。一个会话将简单地由一个时间阈值来定义(即,如果X分钟内没有entires,任何未来的条目都将被分组到一个新会话中) 理想情况下,项目序列可以有一种模糊分组,其中序列中的一个或两个差异仍然可以算作相同并分组在一起 有人知道我如何用SQL解决这个问题吗 更新: 为了澄清,让我们假设这些物品是杂货店的小岛。我有一个月的时间去杂货店。基本的问题是人们使用的是什么岛屿,它的顺序
Id,TimeStamp,Item,UserId
我想为会话中的用户id
确定最常见的项序列。一个会话将简单地由一个时间阈值来定义(即,如果X分钟内没有entires,任何未来的条目都将被分组到一个新会话中)
理想情况下,项目序列可以有一种模糊分组,其中序列中的一个或两个差异仍然可以算作相同并分组在一起
有人知道我如何用SQL解决这个问题吗
更新:
为了澄清,让我们假设这些物品是杂货店的小岛。我有一个月的时间去杂货店。基本的问题是人们使用的是什么岛屿,它的顺序是什么。他们最常去的岛是1,2,3
还是1,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)*/
sequence
列将在给定的UserId
的序列中的所有记录之间共享。你可以在上面分组或做任何你想做的事情。这听起来像是老式的关联规则挖掘问题(但排序更容易),如果我正确理解了这个问题,那么这个问题就没有一个[有效的]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
注:上述解决方案可针对性能进行优化#tempStore可以删除。如果表上没有“id”列,这是没有意义的,因为不能保证表中记录的顺序。@FilipDeVos:有一个id字段,将更新问题。但是序列应该基于时间戳,而不是id。这让我想起了一点这个问题,即使是微不足道的样本也是非常可怕的<代码>创建表格演示(sessionId int,Item int)插入表格值(1,1)插入表格值(1,2)插入表格值(2,1)插入表格值(2,2)
这涉及到大量的自我测试joining@Kyle:你能发布一个样本数据集和期望的输出吗?我不是这样理解这个问题的。您正在查找具有相同项的相邻孤岛
我以为OP想要查找项的模式
。因此,如果Item1,Item2,Item3
是一个常见的序列。@马丁:从序列中的一个或两个差异仍然可以算作相同的,并组合在一起,我判断连续序列是@op想要的。当然,我的问题不是这样的:)@Martin的解释是正确的。至少从一开始,请求中的一两个差异部分可能只是额外的积分:-P还有,最后一个from应该from q
对吗?@Kyle:当然,更正了。所以如果1,2,3
是一个序列,那么1,3,5
会是吗?换句话说,序列应该是连续的还是不断增加的?@Quassnoi。我正在寻找所取物品的路径。出于这个原因,你可以说这是一家杂货店,商品都是小岛。在一次访问中,他们是否去了1号岛、3号岛,然后又回到1号岛,然后结帐?所以序列可以是任何东西。
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)