试图找到随时间T-SQL出现的最大次数

时间:2014-01-27 15:34:54

标签: sql sql-server

我的数据记录了2013年全年流程的StartDateTimeEndDateTimeDATETIME2}。

我的任务是找到全年任何特定时间运行流程的最大次数。

我已经编写了一些代码来检查每分钟/秒在特定时间运行了多少进程,但是这需要很长时间才能让它运行一整年。

这是代码(在这种情况下,检查日期为25/10/2013的每分钟)

CREATE TABLE dbo.#Hit
(
  ID INT IDENTITY (1,1) PRIMARY KEY,
  Moment DATETIME2,
  COUNT INT
 )

DECLARE @moment DATETIME2 

SET @moment = '2013-10-24 00:00:00'

WHILE @moment < '2013-10-25'
BEGIN

    INSERT INTO #Hit ( Moment, COUNT )

    SELECT @moment, COUNT(*) 
    FROM dbo.tblProcessTimeLog
    WHERE ProcessFK IN (25)
    AND @moment BETWEEN StartDateTime AND EndDateTime
    AND DelInd = 0

    PRINT @moment

    SET @moment = DATEADD(MINute,1,@moment)
END

SELECT * FROM #Hit
ORDER BY COUNT DESC

任何人都可以考虑如何获得类似的结果(我只需要在任何给定时间运行最多的进程),但是全年都可以吗?

由于

3 个答案:

答案 0 :(得分:0)

创建一个表T,其行代表一些时间段 该表可能是一个临时表(取决于您的情况)。

说:

row 1 - [from=00:00:00, to=00:00:01)
row 2 - [from=00:00:01, to=00:00:02)
row 3 - [from=00:00:02, to=00:00:03)

等等。

然后从主表中加入 (我认为tblProcessTimeLog)到这个表格 基于中记录的日期时间值 tblProcessTimeLog

一年只有大约五十万分钟 所以在T中存储的行数并不多。

答案 1 :(得分:0)

DECLARE @d DATETIME = '20130101'; -- the first day of the year you care about

;WITH m(m) AS 
(  -- all the minutes in a day
  SELECT TOP (1440) ROW_NUMBER() OVER (ORDER BY number) - 1
  FROM master..spt_values
),
d(d) AS 
(  -- all the days in *that* year (accounts for leap years vs. hard-coding 365)
  SELECT TOP (DATEDIFF(DAY, @d, DATEADD(YEAR, 1, @d))) DATEADD(DAY, number, @d)
    FROM master..spt_values WHERE type = N'P' ORDER BY number
),
x AS
(  -- all the minutes in *that* year
  SELECT moment = DATEADD(MINUTE, m.m, d.d) FROM m CROSS JOIN d
)
SELECT TOP (1) WITH TIES -- in case more than one at the top
  x.moment, [COUNT] = COUNT(l.ProcessFK)
FROM x 
INNER JOIN dbo.tblProcessTimeLog AS l
  ON x.moment >= l.StartDateTime 
  AND x.moment <= l.EndDateTime
WHERE l.ProcessFK = 25 AND l.DelInd = 0
GROUP BY x.moment
ORDER BY [COUNT] DESC;

See this post for why I don't think you should use BETWEEN for range queries, even in cases where it does semantically do what you want

答案 2 :(得分:0)

我最近从SO中提取了一些代码,试图解决“岛屿和间隙”问题,并且该算法可以帮助您解决问题。

我们的想法是,您希望找到具有最多启动过程的时间点,就像在表达式中找出括号中最深的嵌套一样:

((()(((((这里最深处,6)))))

这个sql会为你生成这个结果(我包含了一个包含样本数据的临时表):

    /*
    CREATE TABLE #tblProcessTimeLog
    (
        StartDateTime DATETIME2,
        EndDateTime DATETIME2
    )

    -- delete from #tblProcessTimeLog

    INSERT INTO #tblProcessTimeLog (StartDateTime, EndDateTime)
    Values ('1/1/2012', '1/6/2012'), 
        ('1/2/2012', '1/6/2012'),
        ('1/3/2012', '1/6/2012'), 
        ('1/4/2012', '1/6/2012'), 
        ('1/5/2012', '1/7/2012'),
        ('1/6/2012', '1/8/2012'),
        ('1/6/2012', '1/10/2012'), 
        ('1/6/2012', '1/11/2012'), 
        ('1/10/2012', '1/12/2012'), 
        ('1/15/2012', '1/16/2012') 
    ;
    */
    with cteProcessGroups (EventDate, GroupId) as
(
    select EVENT_DATE, (E.START_ORDINAL - E.OVERALL_ORDINAL) GROUP_ID
    FROM
    (
        select EVENT_DATE, EVENT_TYPE, 
        MAX(START_ORDINAL) OVER (ORDER BY EVENT_DATE, EVENT_TYPE ROWS UNBOUNDED PRECEDING) as START_ORDINAL,
        ROW_NUMBER() OVER (ORDER BY EVENT_DATE, EVENT_TYPE) AS OVERALL_ORDINAL
        from
        (
            Select StartDateTime AS EVENT_DATE, 1 as EVENT_TYPE, ROW_NUMBER() OVER (ORDER BY StartDateTime) as START_ORDINAL
            from #tblProcessTimeLog

            UNION ALL

            select EndDateTime, 0 as EVENT_TYPE, NULL
            FROM #tblProcessTimeLog
        ) RAWDATA
    ) E
)
select Max(EventDate) as EventDate, count(GroupId) as OpenProcesses
from cteProcessGroups
group by (GroupId)
order by COUNT(GroupId) desc

结果:

EventDate   OpenProcesses
2012-01-05 00:00:00.0000000 5
2012-01-06 00:00:00.0000000 4
2012-01-15 00:00:00.0000000 2
2012-01-10 00:00:00.0000000 2
2012-01-08 00:00:00.0000000 1
2012-01-07 00:00:00.0000000 1
2012-01-11 00:00:00.0000000 1
2012-01-06 00:00:00.0000000 1
2012-01-06 00:00:00.0000000 1
2012-01-06 00:00:00.0000000 1
2012-01-16 00:00:00.0000000 1

请注意,“中间”行没有任何意义。基本上这个输出只是为了告诉你什么时候活动最多。看看输出中的其他行,在1/8上只有1个进程运行(实际上有3个)。但是,此代码的工作方式是通过将组中并发的进程分组,您可以计算并发进程的数量。返回的日期是最大并发进程开始的时间。它没有告诉你他们要花多长时间,但你可以通过额外的查询来解决这个问题。 (一旦你知道最多的日期,你可以在日期使用BETWEEN语句找出具体的过程ID。)

希望这有帮助。