查询以在两个日期之间创建记录

时间:2012-03-31 14:55:09

标签: sql-server tsql

我有一个包含以下字段的表格(其中包括)

TagID
TagType
EventDate
EventType

EventType可以填充“通过检查”,“检查失败”或“已修复”(实际上有很多其他的,但我的问题简化了这一点)

标签可能会在检查失败和最终修复之间持续数月...在这种状态下,它们被视为“等待修复”。即使在确定标签失败后,每个月仍会对标签进行检查。 (并且要清楚,“检查失败”并不意味着被检查的项目根本不起作用......它仍然有效,只是不是100%的容量......这就是为什么我们仍然对它进行检查。)< / p>

我需要创建一个查询,按TagType,Month和Year计算等待修复的标记数。最终结果表看起来像这样,例如

 TagType      EventMonth      EventYear     CountofTagID  
 xyz               1            2011               3  
 abc               1            2011               2  
 xyz               2            2011               2>>>>>>>>>>>>indicating a repair had been made since 1/2011  
 abc               2            2011               2  
 and so on

应该在当月的最后一天评估“等待修复”状态

这让我很困惑......

我想到的是开发一个返回的查询:

 TagID,
 TagType,
 FailedInspectionDate, and
 NextRepairDate,

然后尝试在两个日期之间做几个月的事情,但这看起来非常低效。

非常感谢任何帮助。

更新
多一点研究,从问题中解脱出来,以不同的方式思考,给了我以下方法。我确信它不高效或优雅,但它有效。欢迎提出改进意见。

declare @counter int
declare @FirstRepair date
declare @CountMonths as int

set @FirstRepair = (<Select statement to find first repair across all records>)
set @CountMonths = (<select statement to find the number of months between the first repair across all records and today>)
--clear out the scratch table
delete from dbo.tblMonthEndDate
set @counter=0
while @counter <=@CountMonths --fill the scratch table with the date of the last day of every month from the @FirstRepair till today
begin
insert into dbo.tblMonthEndDate(monthenddate) select             dbo.lastofmonth(dateadd(m,@counter, @FirstRepair))
set @counter = @counter+1
end
--set up a CTE to get a cross join between the scratch table and the view that has the associated first Failed Inspection and Repair
;with Drepairs_CTE (FacilityID, TagNumber, CompType, EventDate) 
AS
(
SELECT dbo.vwDelayedRepairWithRepair.FacilityID,     dbo.vwDelayedRepairWithRepair.TagNumber, dbo.vwDelayedRepairWithRepair.CompType, 
           dbo.tblMonthEndDate.MonthEndDate
FROM  dbo.vwDelayedRepairWithRepair INNER JOIN
           dbo.tblMonthEndDate ON dbo.vwDelayedRepairWithRepair.EventDate <= dbo.tblMonthEndDate.MonthEndDate AND 
           dbo.vwDelayedRepairWithRepair.RepairDate >= dbo.tblMonthEndDate.MonthEndDate
)
--use the CTE to build the final table I want
Select FacilityID, CompType, Count(TagNumber), MONTH(EventDate),     YEAR(EventDate), 'zzz' as EventLabel
FROM  Drepairs_CTE
GROUP BY FacilityID, CompType, MONTH(EventDate), YEAR(EventDate)`    

结果集最终如下所示:

FacilityID  CompType  Count  Month      Year  Label
1        xyz    2   1   2010    zzz
1        xyz    1   2   2010    zzz
1        xyz    1   7   2009    zzz

1 个答案:

答案 0 :(得分:1)

这是一个递归CTE,它生成以修复表中的最小日期开始并以最大日期结束的间隔中月份的最后日期表。

;with tableOfDates as (
  -- First generation returns last day of month of first date in repair database
  -- and maximum date 
  select dateadd (m, datediff (m, 0, min(eventDate)) + 1, 0) - 1 startDate,
         max(eventDate) endDate
    from vwDelayedRepairWithRepair
  union all
  -- Last day of next month
  select dateadd (m, datediff (m, 0, startDate) + 2, 0) - 1, 
         endDate
  from tableOfDates
  where startDate <= endDate
)
select * 
from tableOfDates
-- If you change the CTE,
-- Set this to reasonable number of months 
-- to prevent recursion problems. 0 means no limit.
option (maxrecursion 0)
来自tableOfDates的

EndDate列将被忽略,因为它仅用作上限。如果您创建返回间隔中所有日期的UDF,请在选择列表中省略endDate或将其从CTE中删除并替换为参数。

Sql Fiddle playground is here