我需要创建一个表,其中包含从2012年1月1日到现在的每个日期的行,以及每个日期当前打开的错误数。
这是我所拥有的数据,名为Bugs
:BugID
,CreatedDate
,UpdatedDate
,Status
(状态可以是打开或关闭的) )。如果错误已关闭,则UpdatedDate是关闭的日期。如果错误是打开的,那么UpdatedDate是无关紧要的,因为错误是对当前日期开放的。
我可以列出日期,但我不知道该怎么做。
WITH D AS
(
SELECT @RangeStartDate DateValue
UNION ALL
SELECT DateValue + 1
FROM D
WHERE DateValue + 1 < @RangeEndDate
),
答案 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
答案 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的执行计划。