用于计算时间分段数据的运行组计数的SQL查询

时间:2010-04-14 06:47:08

标签: sql

我有一些数据,如:

BUG  DATE                   STATUS
---- ---------------------- --------
9012 18/03/2008 9:08:44 AM  OPEN
9012 18/03/2008 9:10:03 AM  OPEN
9012 28/03/2008 4:55:03 PM  RESOLVED
9012 28/03/2008 5:25:00 PM  CLOSED
9013 18/03/2008 9:12:59 AM  OPEN
9013 18/03/2008 9:15:06 AM  RESOLVED
9013 18/03/2008 9:16:44 AM  CLOSED
9014 18/03/2008 9:17:54 AM  OPEN
9014 18/03/2008 9:18:31 AM  RESOLVED
9014 18/03/2008 9:19:30 AM  CLOSED
9015 18/03/2008 9:22:40 AM  OPEN
9015 18/03/2008 9:23:03 AM  RESOLVED
9015 19/03/2008 12:27:08 PM CLOSED
9016 18/03/2008 9:24:20 AM  OPEN
9016 18/03/2008 9:24:35 AM  RESOLVED
9016 19/03/2008 12:28:14 PM CLOSED
9017 18/03/2008 9:25:47 AM  OPEN
9017 18/03/2008 9:26:02 AM  RESOLVED
9017 19/03/2008 12:30:30 PM CLOSED

我想将其变成这样的东西:

DATE                       OPEN RESOLVED   CLOSED
---------------------- -------- -------- --------
18/03/2008 9:08:44 AM         1        0        0
18/03/2008 9:12:59 AM         2        0        0
18/03/2008 9:15:06 AM         1        1        0
18/03/2008 9:16:44 AM         1        0        1
18/03/2008 9:17:54 AM         2        0        1
18/03/2008 9:18:31 AM         1        1        0
18/03/2008 9:19:30 AM         1        0        2
18/03/2008 9:22:40 AM         2        0        2
18/03/2008 9:23:03 AM         1        1        2
18/03/2008 9:24:20 AM         2        1        2
18/03/2008 9:24:35 AM         1        2        2
18/03/2008 9:25:47 AM         2        2        2
18/03/2008 9:26:02 AM         1        3        2
19/03/2008 12:27:08 PM        1        2        3
19/03/2008 12:28:14 PM        1        1        4
19/03/2008 12:30:30 PM        1        0        5
28/03/2008 4:55:03 PM         0        1        5
28/03/2008 5:25:00 PM         0        0        6

即。保持每个状态的错误运行计数。

这很容易使用游标进行编码,但我想知道你们中的任何一位SQL专家是否可以帮助查询来实现这一目标?

理想情况下mysql,但我很想看到任何可行的内容。

4 个答案:

答案 0 :(得分:2)

With T as
(
Select B.BugDate As MainDate, C.BugID, C.BugDate ,C.Status,row_number() over(partition by B.BugDate,C.BugID order by C.BugDate Desc) As RowNum From Bug B Cross Join Bug C where B.BugDate >=  C.BugDate Group By B.BugDate,C.BugID,C.BugDate, C.Status 
) 

Select T.MainDate ,SUM(CASE WHEN T.Status = 'OPEN' THEN 1 ELSE 0 END) As SUM_OPEN,SUM(CASE WHEN T.Status = 'RESOLVED' THEN 1 ELSE 0 END) As SUM_RESOLVED
,SUM(CASE WHEN T.Status = 'CLOSED' THEN 1 ELSE 0 END) As SUM_CLOSED
From T
where T.RowNum = 1
Group By T.MainDate
Order By T.MainDate

答案 1 :(得分:1)

我自发的方法不会在SQL中,因为它需要一些循环来知道给定下一行时间的每个类别的状态。相反,我将获取原始数据并循环通过,根据每行的STATUS字段修改每个类别的数量,然后输出。如果你想要一个例子,比如说php,我可以给你一个。

另一种方法是将这些数据缓存在一个单独的表中,并在有新操作时更新它。这样你就可以更快地获取它。

答案 2 :(得分:1)

正如您所说的,您希望在任何SQL实现中得到答案,因此我正在为SQL Server 2005及更高版本提供答案,因为我正在使用Windows函数(Row_Number)和CROSS APPLY功能。

想法是获取给定时间的错误的最后状态。

解决方案:

Select  BugDate,
        SUM(Case When RowNum = 1 AND Status = 'OPEN' Then 1 Else 0 End) As Opened,
        SUM(Case When RowNum = 1 AND Status = 'RESOLVED' Then 1 Else 0 End) As Resolved,
        SUM(Case When RowNum = 1 AND Status = 'CLOSED' Then 1 Else 0 End) As Closed
FROM
(
    Select B1.BugDate,T2.BugId,T2.RowNum,T2.[Status]
    from Bug B1
    CROSS APPLY
    (
        SELECT  T1.BugDate,T1.BugId, B.[Status],
                ROW_NUMBER() Over(Partition by B1.BugDate, T1.BugId Order By Case when B.[Status] IS NULL THEN 1000 ELSE 1 END,T1.BugDate Desc) AS RowNum
        FROM
        (
            Select BugDate,BugId
            FROM
            (
                Select Distinct BugDate 
                from Bug
            ) D
            CROSS JOIN
            (
                Select Distinct BugId
                FROm Bug
            ) AS I
        )T1
        LEFT OUTER JOIN BUG B ON T1.BugDate = B.BugDate and T1.BugId = B.BugId
        WHERE  T1.BugDate <= B1.BugDate --AND T1.BugId = B1.BugId
    ) T2
)T1
GROUP BY BugDate 
Order By BugDate

我创建了一个与示例问题中提供的数据集相同的数据集,我得到的结果是:

Date                   Op   Re  Cl

2008-03-18 09:08:44.000 1   0   0
2008-03-18 09:10:03.000 1   0   0
2008-03-18 09:12:59.000 2   0   0
2008-03-18 09:15:06.000 1   1   0
2008-03-18 09:16:44.000 1   0   1
2008-03-18 09:17:54.000 2   0   1
2008-03-18 09:18:31.000 1   1   1
2008-03-18 09:19:30.000 1   0   2
2008-03-18 09:22:40.000 2   0   2
2008-03-18 09:23:03.000 1   1   2
2008-03-18 09:24:20.000 2   1   2
2008-03-18 09:24:35.000 1   2   2
2008-03-18 09:25:47.000 2   2   2
2008-03-18 09:26:02.000 1   3   2
2008-03-19 12:27:08.000 1   2   3
2008-03-19 12:28:14.000 1   1   4
2008-03-19 12:30:30.000 1   0   5
2008-03-28 16:55:03.000 0   1   5
2008-03-28 17:25:00.000 0   0   6

注意:您在结果集中缺少第2行,并且日期为18/03/2008 9:18:31 AM的行在结果中也不正确。

答案 3 :(得分:0)

子查询可以使用,但是它只有三种状态吗?它们是硬编码还是变化

修改

select <TableName>.DATE, (SELECT BUGS FROM CountTable WHERE DATE = <TableName>.DATE AND Status = 'OPEN') as 'OPEN'
        , (SELECT BUGS FROM CountTable WHERE DATE = <TableName>.DATE ANDStatus = 'CLOSED') as 'CLOSED'
        , (SELECT BUGS FROM CountTable WHERE DATE = <TableName>.DATE ANDStatus = 'RESOLVED') as 'RESOLVED'
FROM
<TableName>,
    (   SELECT DATE, STATUS, COUNT(BUG) as BUGS 
    FROM <TableName>
    GROUP BY DATE,STATUS) as CountTable
WHERE CountTable.DATE = <TableName>.DATE

或者,对于更简单的解决方案

SELECT DATE, (SELECT count(BUGS) FROM <TableName> bugs2 WHERE Status = 'OPEN' AND bugs.DATE = bugs2.DATE) as 'OPEN'
        , (SELECT count(BUGS) FROM <TableName> bugs2 WHERE Status = 'CLOSED' AND bugs.DATE = bugs2.DATE) as 'CLOSED'
        , (SELECT count(BUGS) FROM <TableName> bugs2 WHERE Status = 'RESOLVED' AND bugs.DATE = bugs2.DATE) as 'RESOLVED'
FROM <TableName> bugs
group by DATE