我的数据记录了2013年全年流程的StartDateTime
和EndDateTime
(DATETIME2
}。
我的任务是找到全年任何特定时间运行流程的最大次数。
我已经编写了一些代码来检查每分钟/秒在特定时间运行了多少进程,但是这需要很长时间才能让它运行一整年。
这是代码(在这种情况下,检查日期为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
任何人都可以考虑如何获得类似的结果(我只需要在任何给定时间运行最多的进程),但是全年都可以吗?
由于
答案 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;
答案 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。)
希望这有帮助。