查找给定时间间隔内的记录数

Finding count of records in given interval

我有一个 table 用户登录,我想找到在 5 天内登录网站超过 3 次的用户。

例如我的table是:

id | user_id | login_date 
---+---------+--------------
 1 |    10   | 10.1.2014 00:00
 2 |    10   | 11.1.2014 10:10
 3 |    12   | 11.1.2014 11:00
 4 |    10   | 11.1.2014 12:00
 5 |    12   | 12.1.2014 00:00
 6 |    10   | 13.1.2014 10:00
 7 |    12   | 18.1.2014 00:00
 8 |    12   | 22.1.2014 09:00

对于此示例 table,我想选择 user_id 10,因为 he/she 在 5 天内登录了 3 次以上。

你能帮我一下吗?

编辑:我忘了说数据库是 sql server 2008

如果您使用的是 SQL Server 2012+,那么您可以使用 LEAD window 函数来计算任意 3 个连续记录之间的天数差异:

select distinct USER_ID
from (
select USER_ID, 
       datediff(d, login_date,
                   LEAD(login_date, 2) OVER (PARTITION BY user_id 
                                             ORDER BY login_date)) as diffDates
from users ) t
where t.diffDates <= 5

然后简单地 select 天数差等于或小于 5 的那些 USER_IDs

SQL Fiddle Demo

如果您使用的是 SQL Server 2008 或 2005,则可以将 ROW_NUMBER 与自联接结合使用以模拟 LEAD 功能:

;WITH CTE AS (
   SELECT id, user_id, login_date,
          ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY login_date) AS rn
   FROM users
) 
SELECT DISTINCT user_id
FROM (             
   SELECT c1.user_id, 
          DATEDIFF(d, c1.login_date, c2.login_date) AS diffInDays
   FROM CTE AS c1
   INNER JOIN CTE AS c2 ON c1.user_id = c2.user_id AND c1.rn = c2.rn - 2
  ) t
WHERE t.diffInDays <= 5
上述查询中的

diffInDays 本质上是任意 3 次连续用户登录之间的天数滚动差异。

SQL Fiddle Demo

您可以使用以下查询来获取结果。

如您所见,您可以使用 DATEADD 函数来计算参考日期,并使用必须过滤的登录计数大于或等于 3

Select count(*),user_id 
from table_name 
where login_date>=DATEADD (day,-5,GETDATE())
group by user_id  
having COUNT(*) >=3

您可以通过在 user_id 上自行加入 table 来做到这一点,其中 JOIN 获取其加入记录后 5 天内的记录,如下所示:

CREATE TABLE #login
    (
      id INT ,
      user_id INT ,
      login_date DATETIME
    )

INSERT  INTO #login
        ( id, user_id, login_date )
VALUES  ( 1, 10, '2014-01-10 00:00' ),
        ( 2, 10, '2014-01-11 10:10' ),
        ( 3, 12, '2014-01-11 11:00' ),
        ( 4, 10, '2014-01-11 12:00' ),
        ( 5, 12, '2014-01-12 00:00' ),
        ( 6, 10, '2014-01-13 10:00' ),
        ( 7, 12, '2014-01-18 00:00' ),
        ( 8, 12, '2014-01-22 09:00' )

SELECT  t1.user_id ,
        t1.login_date AS FirstDateInLoginPeriod ,
        COUNT(t2.user_id) AS LoginCount
FROM    #login t1
        INNER JOIN #login t2 ON t2.user_id = t1.user_id
                  AND t2.login_date 
                      BETWEEN t1.login_date AND DATEADD(DAY, 5, t1.login_date)
GROUP BY t1.user_id ,
        t1.login_date
HAVING  COUNT(t2.user_id) > 3

DROP TABLE #login

生产:

user_id  FirstDateInLoginPeriod     LoginCount
----------------------------------------------
10       2014-01-10 00:00:00.000    4