按一段时间查询记录和分组

时间:2011-05-17 19:18:55

标签: sql sql-server gaps-and-islands

我有一个可能每天运行几次的应用程序。每次运行都会生成写入表的数据,以报告发生的事件。主报告表看起来像这样:

Id    SourceId    SourceType    DateCreated
5048  433         FILE          5/17/2011 9:14:12 AM
5049  346         FILE          5/17/2011 9:14:22 AM
5050  444         FILE          5/17/2011 9:14:51 AM
5051  279         FILE          5/17/2011 9:15:02 AM
5052  433         FILE          5/17/2011 12:34:12 AM
5053  346         FILE          5/17/2011 12:34:22 AM
5054  444         FILE          5/17/2011 12:34:51 AM
5055  279         FILE          5/17/2011 12:35:02 AM

我可以说有两次运行,但我想要一种方法来查询日期范围,即运行进程的次数。我想有一个查询,导致进程开始的时间和组中的文件数。这个查询有点让我得到我想要的东西,我可以看到什么日期和时间以及运行了多少文件,但不完全是我想要的。例如,它不能容纳从8:58到9:04的运行。它还可以对例如9:02和9:15开始的运行进行分组。

Select dateadd(day,0,datediff(day,0,DateCreated)) as [Date], datepart(hour, DateCreated) as [Hour], Count(*) [File Count]
From   MyReportTable
Where DateCreated between '5/4/2011' and '5/18/2011'
    and SourceType = 'File'
Group By dateadd(day,0,datediff(day,0,DateCreated)), datepart(hour, DateCreated)
Order By dateadd(day,0,datediff(day,0,DateCreated)), datepart(hour, DateCreated)

据我所知,任何靠近的跑步都可能会聚集在一起,我很好。我只希望得到一个粗略的分组。

谢谢!

2 个答案:

答案 0 :(得分:3)

再往前走几步:

SELECT
    Count(Id), 
    DATEPART(year, DateCreated) As yr, 
    DATEPART(month, DateCreated) As mth, 
    DATEPART(day, DateCreated) As day, 
    DATEPART(Hour, DateCreated) as hr, 
    DATEPART(minute, DateCreated) as mnt
FROM 
    MyReportTable
WHERE DateCreated between '5/4/2011' and '5/18/2011'
    and SourceType = 'File'
GROUP BY 
    DATEPART(year, DateCreated), 
    DATEPART(month, DateCreated), 
    DATEPART(day, DateCreated), 
    DATEPART(Hour, DateCreated),
    DATEPART(minute, DateCreated)
ORDER BY 
    DATEPART(year, DateCreated),
    DATEPART(month, DateCreated), 
    DATEPART(day, DateCreated), 
    DATEPART(Hour, DateCreated),
    DATEPART(minute, DateCreated)

修改

要达到15分钟的分辨率,请将最后一列更改为

(DATEPART(minute, DateCreated)/15)

(在选择中添加+1以获得1,2,3,4)。

答案 1 :(得分:2)

如果您确定这些运行是连续的并且不重叠,那么您应该能够使用Id字段来分解您的组。查找仅相隔1的Id字段和相隔大于某个阈值的datedated字段。根据您的数据,看起来运行中的记录最多只能在一分钟内输入,因此安全阈值可能是一分钟或更长时间。

这会让你开始时间

SELECT mrtB.Id, mrtB.DateCreated
FROM MyReportTable AS mrtA
INNER JOIN MyReportTable AS mrtB
    ON (mrtA.Id + 1) = mrtB.Id
WHERE DateDiff(mi, mrtA.DateCreated, mrtB.DateCreated) >= 1

我将称之为DataRunStarts

现在,您可以使用它来获取有关组开始和结束位置的信息

SELECT drsA.Id AS StartID, drsA.DateCreated, Min(drsB.Id) AS ExcludedEndId
FROM DataRunStarts AS drsA, DataRunStarts AS drsB
WHERE (((drsB.Id)>[drsA].[id]))
GROUP BY drsA.Id, drsA.DateCreated

我将称之为DataRunGroups。我调用了最后一个字段“Excluded”,因为它所持有的id只是用于定义将被拉出的id组的结束边界。

现在我们可以使用DataRunGroups和MyReportTable来获取计数

SELECT DataRunGroups.StartID, Count(MyReportTable.Id) AS CountOfRecords
FROM DataRunGroups, MyReportTable
WHERE (((MyReportTable.Id)>=[StartId] And (MyReportTable.Id)<[ExcludedEndId]))
GROUP BY DataRunGroups.StartID;

我将称之为DataRunCounts

现在我们可以将DataRunGroups和DataRunCounts放在一起以获取开始时间和计数。

SELECT DataRunGroups.DateCreated, DataRunCounts.CountOfRecords
FROM DataRunGroups
INNER JOIN DataRunCounts
    ON DataRunGroups.StartID = DataRunCounts.StartID;

根据您的设置,您可能需要在一个查询中执行所有这些操作,但您明白了。此外,第一次和最后一次运行都不会包含在此中,因为第一次运行时没有启动ID,并且最后一次运行没有结束ID。要包含这些内容,您只需对这两个范围进行查询,并将它们与旧的DataRunGroups查询结合在一起以创建新的DataRunGroups。使用DataRunGroups的其他查询将如上所述工作。