Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL来确定连续访问天数的不同时段?_Sql_Sql Server_Date - Fatal编程技术网

SQL来确定连续访问天数的不同时段?

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创建日

最近被问到并得到了一些很好的答案

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)天周期的数量吗


编辑:根据下面的评论,如果某人连续两天,然后是间隔,然后是连续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
;