SQL返回连续记录

标签 sql linq lambda sql-server-2008-r2

一个简单的表格:

ForumPost
--------------
ID (int PK)
UserID (int FK)
Date (datetime)

我希望返回特定用户连续 n 天每天至少发布 1 条帖子的次数。

示例:

User 15844 has posted at least 1 post a day for 30 consecutive days 10 times

我已经用 linq/lambda 标记了这个问题,并且有一个解决方案也很棒。我知道我可以通过迭代所有用户记录来解决这个问题,但这很慢。

最佳答案

有一个方便的技巧,您可以使用 ROW_NUMBER() 来查找连续的条目,想象以下一组日期,其 row_number(从 0 开始):

Date        RowNumber
20130401    0
20130402    1
20130403    2
20130404    3
20130406    4
20130407    5

对于连续条目,如果从值中减去 row_number,则会得到相同的结果。例如

Date        RowNumber   date - row_number
20130401    0           20130401
20130402    1           20130401
20130403    2           20130401
20130404    3           20130401
20130406    4           20130402
20130407    5           20130402

然后,您可以按日期 - row_number 进行分组,以获取连续天数的集合(即前 4 条记录和最后 2 条记录)。

要将其应用到您的示例中,您将使用:

WITH Posts AS
(   SELECT  FirstPost = DATEADD(DAY, 1 - ROW_NUMBER() OVER(PARTITION BY UserID ORDER BY [Date]), [Date]),
            UserID,
            Date
    FROM    (   SELECT  DISTINCT UserID, [Date] = CAST(Date AS [Date])
                FROM    ForumPost
            ) fp
), Posts2 AS
(   SELECT  FirstPost, 
            UserID, 
            Days = COUNT(*), 
            LastDate = MAX(Date)
    FROM    Posts
    GROUP BY FirstPost, UserID
)
SELECT  UserID, ConsecutiveDates = MAX(Days)
FROM    Posts2
GROUP BY UserID;

<强> Example on SQL Fiddle (simple with just most consecutive days per user)

<强> Further example to show how to get all consecutive periods

编辑

我认为上面的内容并没有完全回答问题,这将给出用户发帖的次数,或连续 n 天的发帖次数:

WITH Posts AS
(   SELECT  FirstPost = DATEADD(DAY, 1 - ROW_NUMBER() OVER(PARTITION BY UserID ORDER BY [Date]), [Date]),
            UserID,
            Date
    FROM    (   SELECT  DISTINCT UserID, [Date] = CAST(Date AS [Date])
                FROM    ForumPost
            ) fp
), Posts2 AS
(   SELECT  FirstPost, 
            UserID, 
            Days = COUNT(*), 
            FirstDate = MIN(Date), 
            LastDate = MAX(Date)
    FROM    Posts
    GROUP BY FirstPost, UserID
)
SELECT  UserID, [Times Over N Days] = COUNT(*)
FROM    Posts2
WHERE   Days >= 30
GROUP BY UserID;

<强> Example on SQL Fiddle

关于SQL返回连续记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16014969/

相关文章:

c# - 将 Expression<Func<IBar, T>> 转换为 Expression<Func<Bar, T>>

sql - 一旦找到足够的行,SQL Server TOP 是否会停止处理?

c# - 如何转换项目并在 sitecore 中获取选定的项目?

mysql - Rails 范围 null 返回错误结果

c# - 在 C# 中,如何按对象的多个字段对对象集合进行排序?

c# - LINQ 查询未提取所需的所有记录

c# - Prism EventAggregator 使用 Lambda 表达式订阅与方法名称

python - 如何排序(key=lambda x :) implemented behind the scene?

php - MySQL:如何对每个 WHERE 过滤器进行限制查询

SQL - 在 x 或 y 中出现的组