2010-07-20 135 views
0

Microsoft SQL Server中存在一个表,其中包含记录标识,开始日期,结束日期和数量。针对日期范围的SQL查询,多个开始/结束时间

这个想法是,对于每个记录,范围内的数量/总天数=每日数量。

鉴于包含所有可能日期的表存在,我如何在SQL Server中生成结果集,使其看起来像下面的示例一样?

EX:

RecordID | Start Date | End Date | Quantity 
1  | 1/1/2010 | 1/5/2010 | 30000 
2  | 1/3/2010 | 1/9/2010 | 20000 
3  | 1/1/2010 | 1/7/2010 | 10000 

Results as 
1  | 1/1/2010 | QTY (I can do the math easy, just need the dates view) 
1  | 1/2/2010 | 
1  | 1/3/2010 | 
1  | 1/4/2010 | 
1  | 1/3/2010 | 
2  | 1/4/2010 | 
2  | 1/5/2010 | 
2  | 1/6/2010 | 
2  | 1/7/2010 | 
2  | 1/8/2010 | 
2  | 1/9/2010 | 
3  | 1/1/2010 | 
3  | 1/2/2010 | 
3  | 1/3/2010 | 
3  | 1/4/2010 | 
3  | 1/5/2010 | 
3  | 1/6/2010 | 
3  | 1/7/2010 | 

分组的日期,我能得到那么得到的那一天量的总和不过最终的结果集不能总因为这可能会排除某些记录用户提供过滤器在路上。

EDIT

为了澄清,这仅仅是一个示例。过滤器是无关紧要的,因为我可以加入到侧面来获取结果中与记录ID相关的详细信息。

真实数据包含每周增加的N个记录,日期从不相同。可能有2000条记录具有不同的开始日期和结束日期......这是我想为其生成视图。我可以正确加入数据,以完成我需要的其余部分。

我还应该提到这是针对过去,现在和将来的数据。我很想摆脱一个临时的日期表。我使用递归查询来获取50年内存在的所有日期,但这超出了MAXRECURSION对于视图的限制,我无法使用。

+0

我不知道我的理解对用户提供的滤光器的信息。你能提供更多细节吗? – bobs 2010-07-20 21:50:39

+0

这些过滤器真的无关紧要。我会把这个列表加入到主列表中,其中包含关于数量等的信息,并可以使用这些事实来推导出所有的值。 – Mohgeroth 2010-07-20 23:09:38

回答

3

回答

select RecordId,d.[Date], Qty/ COUNT(*) OVER (PARTITION BY RecordId) AS Qty 
from EX join Dates d on d.Date between [Start Date] and [End Date] 
ORDER BY RecordId,[Date] 

注:以下演示热膨胀系数使用date数据类型是SQL Server 2008中的一般方法应该为SQL2005工作,但也。

测试用例

/*CTEs for testing purposes only*/ 

WITH EX AS 
(
    SELECT 1 AS RecordId, 
    cast('1/1/2010' as date) as [Start Date], 
    cast('1/5/2010' as date) as [End Date], 
    30000 AS Qty 
union all 
    SELECT 2 AS RecordId, 
    cast('1/3/2010' as date) as [Start Date], 
    cast('1/9/2010' as date) as [End Date], 
    20000 AS Qty 
),Dates AS /*Dates Table now adjusted to do greater range*/ 
(

SELECT DATEADD(day,s1.number + 2048*s2.number,'1990-01-01') AS [Date] 
FROM master.dbo.spt_values s1 CROSS JOIN master.dbo.spt_values s2 
where s1.type='P' AND s2.type='P' and s2.number <= 8 
order by [Date] 
) 


select RecordId,d.[Date], Qty/ COUNT(*) OVER (PARTITION BY RecordId) AS Qty 
from EX join Dates d on d.Date between [Start Date] and [End Date] 
ORDER BY RecordId,[Date] 

结果

RecordId Date  Qty 
----------- ---------- ----------- 
1   2010-01-01 6000 
1   2010-01-02 6000 
1   2010-01-03 6000 
1   2010-01-04 6000 
1   2010-01-05 6000 
2   2010-01-03 2857 
2   2010-01-04 2857 
2   2010-01-05 2857 
2   2010-01-06 2857 
2   2010-01-07 2857 
2   2010-01-08 2857 
2   2010-01-09 2857 
+0

我没有提到这是过去,现在和将来的数据。我喜欢这样的想法,即我不必从临时表中获取日期,但不幸的是,这可能会向前推进两年,对这些结果使用此查询不会为未来的数据产生任何结果。我很想摆脱这个临时日期表,尽管... – Mohgeroth 2010-07-20 23:17:35

+0

@Mohgeroth - 具有日期索引的专用日期表将是最有效的解决方案。你应该能够轻松地调整我的查询来查看,而不是我的演示日期表。 – 2010-07-20 23:55:46

+0

你是什么意思“未来日期”?他的查询适用于长达22年以上的跨度,无论他们是过去还是未来。如果您的意思是您希望在数量为0的数量列表中看到将来的日期,例如“2011-01-01 0”,那么您必须包含一个指定开始和结束总日期范围的参数。 – ErikE 2010-07-20 23:59:36

1

我想你可以试试这个。

SELECT [Quantities].[RecordID], [Dates].[Date], SUM([Quantity]) 
FROM [Dates] 
JOIN [Quantities] on [Dates].[Date] between [Quantities].[Start Date] and [End Date] 
GROUP BY [Quantities].[RecordID], [Dates].[Date] 
ORDER BY [Quantities].[RecordID], [Dates].[Date] 
+0

美丽。我没想过在我的加入手术中使用。我仍然有这个我希望消除的日期表,但如果不能这样做,这是一个干净的解决方案 – Mohgeroth 2010-07-20 23:08:41

相关问题