SQL来确定连续访问天数的不同时段?
最近被问到并得到了一些很好的答案 Jeff的问题在于找到连续登录系统天数为(n)天的用户。使用数据库表结构,如下所示: Id UserId CreationDate ------ ------ ------------ 750997 12 2009-07-07 18:42:20.723 750998 15 2009-07-07 18:42:20.927 751000 19 2009-07-07 18:42:22.283 用户Id创建日期 ------ ------ ------------ 750997 12 2009-07-07 18:42:20.723 750998 15 2009-07-07 18:42:20.927 751000 19 2009-07-07 18:42:22.283 先读清楚,然后 我对确定一个用户有多少不同的(n)天周期的问题很感兴趣 有人能设计一个快速的SQL查询,返回用户列表和他们拥有的不同(n)天周期的数量吗SQL来确定连续访问天数的不同时段?,sql,sql-server,date,Sql,Sql Server,Date,最近被问到并得到了一些很好的答案 Jeff的问题在于找到连续登录系统天数为(n)天的用户。使用数据库表结构,如下所示: Id UserId CreationDate ------ ------ ------------ 750997 12 2009-07-07 18:42:20.723 750998 15 2009-07-07 18:42:20.927 751000 19 2009-07-07 18:42:22.283 用户Id创建日
编辑:根据下面的评论,如果某人连续两天,然后是间隔,然后是连续4天,然后是间隔,然后是连续8天。这将是3个“不同的4天周期”。8天的周期应计为两个背对背的4天周期。这与我的测试数据非常吻合
DECLARE @days int
SET @days = 30
SELECT DISTINCT l.UserId, (datediff(d,l.CreationDate, -- Get first date in contiguous range
(
SELECT min(a.CreationDate ) as CreationDate
FROM UserHistory a
LEFT OUTER JOIN UserHistory b
ON a.CreationDate = dateadd(day, -1, b.CreationDate ) AND
a.UserId = b.UserId
WHERE b.CreationDate IS NULL AND
a.CreationDate >= l.CreationDate AND
a.UserId = l.UserId
) )+1)/@days as cnt
INTO #cnttmp
FROM UserHistory l
LEFT OUTER JOIN UserHistory r
ON r.CreationDate = dateadd(day, -1, l.CreationDate ) AND
r.UserId = l.UserId
WHERE r.CreationDate IS NULL
ORDER BY l.UserId
SELECT UserId, sum(cnt)
FROM #cnttmp
GROUP BY UserId
HAVING sum(cnt) > 0
我的答案似乎没有出现 我会再试一次 Rob Farley对原始问题的回答有一个方便的好处,即包括连续天数
with numberedrows as
(
select row_number() over (partition by UserID order by CreationDate) - cast(CreationDate-0.5 as int) as TheOffset, CreationDate, UserID
from tablename
)
select min(CreationDate), max(CreationDate), count(*) as NumConsecutiveDays, UserID
from numberedrows
group by UserID, TheOffset
使用整数除法,只需将连续天数除以,即可得到整个连续周期所覆盖的“不同(n)天周期”数…-2/4=0
-4/4=1
-8/4=2
-9/4=2
-等等等等 以下是我对Rob针对您需求的回答的看法…
(我真的很喜欢,去看看解释,它启发了我的思考!)
唯一真正的区别是,我把Rob的结果拿出来,然后在另一组中运行…所以-我将从上一个问题开始,它列出了连续运行的每一天。然后我将根据userid和numconsecurivedays对其进行分组,以计算这些用户的运行天数
with numberedrows as
(
select row_number() over (partition by UserID order by CreationDate) - cast(CreationDate-0.5 as int) as TheOffset, CreationDate, UserID
from tablename
)
,
runsOfDay as
(
select min(CreationDate), max(CreationDate), count(*) as NumConsecutiveDays, UserID
from numberedrows
group by UserID, TheOffset
)
select UserID, NumConsecutiveDays, count(*) as NumOfRuns
from runsOfDays
group by UserID, NumConsecutiveDays
;
当然,如果你想过滤这个,只考虑某个长度的运行,那么在最后一个查询中放置“NoUnStudioVoDeAs>= @天”。< /P> 现在,如果您想将16天的运行计算为三次5天的运行,那么每次运行都将计算为numconsecurivedays/@runlength(将对每个整数进行取整)。因此,现在不要只计算每个的数量,而是使用SUM。您可以使用上面的查询并使用SUM(NumOfRuns*numconsecurivedays/@runlength),但是如果您理解了逻辑,那么下面的查询就容易一些
with numberedrows as
(
select row_number() over (partition by UserID order by CreationDate) - cast(CreationDate-0.5 as int) as TheOffset, CreationDate, UserID
from tablename
)
,
runsOfDay as
(
select min(CreationDate), max(CreationDate), count(*) as NumConsecutiveDays, UserID
from numberedrows
group by UserID, TheOffset
)
select UserID, sum(NumConsecutiveDays / @runlength) as NumOfRuns
from runsOfDays
where NumConsecutiveDays >= @runlength
group by UserID
;
希望这有帮助
Rob你能详细说明一下你对“不同(n)天周期”的定义吗?如果有人连续两天,然后是间隔,然后是连续4天,然后是间隔,然后是连续8天,这是2个“不同的4天周期”还是3个?(8天周期计为两个背对背的4天周期?)我将编辑这个问题,但使用您的示例,这将是3个不同的4天周期。
with numberedrows as
(
select row_number() over (partition by UserID order by CreationDate) - cast(CreationDate-0.5 as int) as TheOffset, CreationDate, UserID
from tablename
)
,
runsOfDay as
(
select min(CreationDate), max(CreationDate), count(*) as NumConsecutiveDays, UserID
from numberedrows
group by UserID, TheOffset
)
select UserID, sum(NumConsecutiveDays / @runlength) as NumOfRuns
from runsOfDays
where NumConsecutiveDays >= @runlength
group by UserID
;