SQL - 计算每天打开的总错误数

时间:2014-07-09 13:59:04

标签: sql sql-server

我需要创建一个表,其中包含从2012年1月1日到现在的每个日期的行,以及每个日期当前打开的错误数。

这是我所拥有的数据,名为BugsBugIDCreatedDateUpdatedDateStatus(状态可以是打开或关闭的) )。如果错误已关闭,则UpdatedDate是关闭的日期。如果错误是打开的,那么UpdatedDate是无关紧要的,因为错误是对当前日期开放的。

我可以列出日期,但我不知道该怎么做。

WITH D AS ( SELECT @RangeStartDate DateValue UNION ALL SELECT DateValue + 1 FROM D
WHERE DateValue + 1 < @RangeEndDate ),

6 个答案:

答案 0 :(得分:1)

WITH D AS
 (
  SELECT @RangeStartDate DateValue
  UNION ALL
  SELECT DateValue + 1
  FROM D

  WHERE DateValue + 1 < @RangeEndDate
 )
Select D.DateValue, coalesce(count(BugID),0)
FROM D
LEFT JOIN Bugs B 
  on B.CreateDate <= D.Datevalue
 and (B.UpdateDate >= D.DateValue or B.UpdateDate is null)
Group By D.DateValue

意图:从d返回所有日期,只返回与bug匹配的记录 bug创建日期小于日期,bug大于updateddate,或者updatedate为null。

答案 1 :(得分:0)

我认为您可以使用以下查询

;WITH D AS
 (
  SELECT @RangeStartDate DateValue
  UNION ALL
  SELECT DateValue + 1
  FROM D
  WHERE DateValue + 1 < @RangeEndDate
 )
 SELECT D.DateValue, COUNT(ISNULL(BugID,0))
 FROM D LEFT JOIN Bugs ON D.DateValue >= Bugs.CreatedDate 
    AND (D.DateValue <= Bugs.UpdatedDate OR Bugs.UpdatedDate IS NULL)
 GROUP BY D.DateValue

答案 2 :(得分:0)

从您的CTE开始日期,我会使用这样的查询(当错误仍然打开时我认为UpdatedDate = NULL):

WITH D AS
 (
  SELECT @RangeStartDate DateValue
  UNION ALL
  SELECT DateValue + 1
  FROM D

  WHERE DateValue + 1 < @RangeEndDate
 ),
SELECT D.DateValue,
       (SELECT COUNT(*)
        FROM Bugs
        WHERE CreatedDate <= D.DateValue
          AND (UpdatedDate > D.DateValue
               OR UpdatedDate IS NULL)) AS NumberOfBugs
FROM D

答案 3 :(得分:0)

declare @bugs table(BUGID int,Createddate datetime,Updateddate datetime,Status char(1))
insert into @bugs
Select 1,'20140101',NULL,'I'
UNION Select 2,'20140102','20140110','U'
UNION Select 3,'20140103','20140110','C'
UNION Select 4,'20140104',NULL,'I'
UNION Select 5,'20140105','20140110','U'
UNION Select 6,'20140106','20140109','C'
UNION Select 10,'20140101','20140110','C'

declare @RangeStartDate datetime
declare @RangeEndDate datetime
select @RangeStartDate ='20140101'
select @RangeEndDate ='20140201'

;WITH D AS
 (
  SELECT @RangeStartDate DateValue
  UNION ALL
  SELECT DateValue + 1
  FROM D
  WHERE DateValue + 1 < @RangeEndDate
 )
Select D.* ,
(Select SUM(dd) from
(Select 1 as DD from @bugs b where  b.Createddate<=d.DateValue and ((b.Status<>'C')  or (b.Status='C' and b.Updateddate>=d.DateValue)) ) a) 
from D

答案 4 :(得分:0)

CTE中,您应该使用适当的函数来操作日期,例如DATEADD,以便在数据类型更改为DateTime2时使代码继续有效

代码非常简单:选择日期,在该日期之前获取CreatedDate的所有错误,并计算UpdateDate之后日期为已关闭的错误的日期,以及日期的日期在UpdateDate之前获取仍然打开的错误。

确实不需要状态字段,因为错误的状态是通过让UpdateDate不是NULL来确定的。

DECLARE @RangeStartDate datetime2 = '20120201'
DECLARE @RangeEndDate datetime2 = '20120228'

;WITH D AS (
  SELECT @RangeStartDate DateValue
  UNION ALL
  SELECT DATEADD(d, 1, DateValue)
  FROM   D
  WHERE  DATEADD(d, 1, DateValue) <= @RangeEndDate
)
SELECT DateValue
     , BugsOpen = COUNT(CASE WHEN DateValue < COALESCE(UpdatedDate, '99991231') 
                             THEN 1 
                             ELSE NULL 
                        END)
     , BugsClose = COUNT(CASE WHEN DateValue >= COALESCE(UpdatedDate, '99991231')
                              THEN 1 
                              ELSE NULL 
                         END)
FROM   D
       LEFT JOIN Bugs ON DateValue >= CreatedDate
GROUP BY DateValue

SQLFiddle demo

答案 5 :(得分:0)

虽然已经发布的答案中至少有几个似乎有效,但他们都继续使用递归cte进行计数。这与使用while循环相同。这很慢。我强烈建议使用数字/计数表来表示此类事情。它会快得多。我在这里实现它的方式导致0次读取以生成一个包含10,000行的表。

if OBJECT_ID('tempdb..#Bugs') is not null
    drop table #Bugs

create table #Bugs
(
    BugID int identity not null primary key clustered, 
    BugName varchar(10) not null,
    CreatedDate datetime not null default getdate(), 
    UpdatedDate datetime null, 
    IsClosed bit not null default 0
)

insert #Bugs(BugName, CreatedDate, UpdatedDate)
select 'Bug 1', GETDATE(), null union all
select 'Bug 2', GETDATE() - 3, null union all
select 'Bug 3', GETDATE() -5, GETDATE() -3 union all
select 'Bug 4', getdate()-8, GETDATE() - 7

select * from #Bugs

declare @RangeStart datetime = getdate() - 10;

WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )
select DATEADD(day, N, @RangeStart), *
from cteTally t
cross apply
(
    select COUNT(*) as OpenBugCount
    from #Bugs
    where CreatedDate <= DATEADD(day, N, @RangeStart)
        AND (UpdatedDate >= DATEADD(day, N, @RangeStart) OR UpdatedDate is null)
) b
where t.N <= DATEDIFF(day, @RangeStart, getdate());

看看这种计数方式与rCTE的执行计划。