在一个表中收集多个计数

时间:2014-04-15 14:18:06

标签: php mysql sql perl

我有一份工作日志表。我想知道每台服务器上每小时运行的作业数量是多少。

我知道我可以用PHP或PERL来做这件事。是否有纯SQL方法来完成此任务?

我相信我需要做一个while循环,以日期/时间变量和整数变量为最大分钟。可以在sql语句中完成while循环,还是需要存储过程?

这是我写过的存储过程。我知道它还没有存储任何数据。

当我尝试运行时,MySQL抱怨没有选择数据库:

DELIMITER //

CREATE PROCEDURE `StatsByMinute`(IN StartDate datetime, 
                                 IN NumMin integer, 
                                 IN WSServer varchar(16))
BEGIN
   DECLARE c INT;
   SET c = -1;
   WHILE c <= NumMin DO 
      SELECT COUNT(*) 
      FROM tws.SymphonyJobs 
      WHERE JobStarted   <= TIMESTAMPADD(MINUTE,1+c,StartDate)
        AND JobCompleted >= TIMESTAMPADD(MINUTE,2+c,StartDate)
        AND JobWS= WSServer;
      SET c=c+1; 
   END WHILE;
END

任何帮助都将不胜感激。

示例数据:

StreamWS    JobStarted  JobCompleted
Server1 4/12/2014 21:31 4/12/2014 21:53
Server1 4/12/2014 21:31 4/12/2014 21:53
Server1 4/12/2014 21:31 4/12/2014 21:53
Server1 4/12/2014 21:31 4/12/2014 21:53
Server1 4/12/2014 21:31 4/12/2014 21:53
Server1 4/12/2014 21:31 4/12/2014 21:53
Server1 4/12/2014 21:31 4/12/2014 21:53
Server1 4/12/2014 21:31 4/12/2014 21:53
Server2 4/13/2014 0:01  4/13/2014 0:03
Server2 4/13/2014 0:01  4/13/2014 0:03
Server2 4/13/2014 0:01  4/13/2014 0:03
Server2 4/13/2014 0:01  4/13/2014 0:03
Server2 4/13/2014 0:01  4/13/2014 3:28
Server2 4/13/2014 0:02  4/13/2014 0:03
Server2 4/13/2014 0:02  4/13/2014 0:03
Server2 4/13/2014 0:02  4/13/2014 0:03
Server2 4/13/2014 0:02  4/13/2014 0:03
Server2 4/13/2014 0:02  4/13/2014 0:03
Server2 4/13/2014 0:02  4/13/2014 0:03
Server2 4/13/2014 0:02  4/13/2014 0:03

1 个答案:

答案 0 :(得分:0)

如果您在每次作业执行时都在作业表中记录了足够的数据,包括准确的计时,您的答案就是在表格中进行选择并按分钟对作业进行分组。我不熟悉MySQL,但我可以在SQL Server中向您展示一个可以完成这项工作的简单选择:

SELECT DATEPART(MINUTE,YourDate), Count(YourJob) 
FROM #X
GROUP BY  DATEPART(MINUTE,YourDate), YourJob

DATEPART是SQL Server中的一个函数,它可以获取日期的特定部分(在本例中为分钟)。您可能在MySQL中找到类似的功能?然后,您只需使用此功能分组您的行,然后按作业计数。这将显示每分钟完成的工作数。

更新:在MySQL中试试这个:

SELECT MINUTE(YourDate), Count(YourJob) 
FROM #X
GROUP BY  MINUTE(YourDate), YourJob

更新2:希望这对您更有效...

SELECT StreamWS, DATEFORMAT(JobStarted,'%d %m %y %H') as Date, MINUTE(JobStarted) StartedMinute, 
Count(StreamWS) Total
FROM #YourTable
WHERE  STR_TO_DATE(JobStarted, '%d/%m/%Y') BETWEEN '01-Jan-2013' AND '01-Jun-2015'
GROUP BY  StreamWS, DATEFORMAT(JobStarted,'%d %m %y'), MINUTE(JobStarted)

在此查询中,您首先按服务器进行分组,以便您能够查看每个服务器的结果,然后查看实际发生的日期(您可以在此处更改参数,以便您可以像你需要,例如每小时,或每天,或每个月,然后每分钟分割每分钟的计数。在Where子句中,您可以添加所需的日期范围。

有关MySQL中日期操作的更多信息: http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html#function_date-format

更新3:

我正在考虑解决这个问题的另一个选择是递归CTE,但经过一些研究后我发现MySQL并不支持它们(https://dba.stackexchange.com/questions/46061/mysql-equivalent-of-with-in-oracle),我会告诉你它是怎么样的(我虽然没有测试它,所以你可以用不同的方式做同样的事情......

WITH X (StreamWS, MyCount, [Minutes]) AS
(
SELECT StreamWS, 1 as MyCount, DATEDIFF(MINUTE,JobStarted,JobCompleted) FROM #TransactionLog T
UNION ALL 
SELECT X.StreamWS, X.MyCount+1, X.Minutes-1 FROM X 
WHERE X.Minutes>0 and X.MyCount<X.Minutes

--JOIN #TransactionLog T ON X.StreamWS = T.StreamWS
--AND DATEDIFF(MINUTE,T.JobStarted,T.JobCompleted)<X.MyCount<
)
SELECT * FROM X

这个想法是复制它运行的每一分钟的条目(作业),例如对于样本表中的服务器1,你运行22分钟(从21:31到21:53):你可以有一个新的时态表,其中Server1被创建为每分钟一行(即22次):

StreamWS MyCount     Time
-------- ----------- -----------
Server1  1           4/12/2014 21:31
Server1  2           4/12/2014 21:32
Server1  3           4/12/2014 21:33
Server1  4           4/12/2014 21:34

...

如果对所有服务器执行此操作,则可以查询此新时间表以查找特定范围。这应该可以为您提供更准确的作业结果,即每分钟在该日期范围内运行的作业。