SQL 查询日期范围、多个开始/结束时间

发布于 2024-09-10 13:02:51 字数 1195 浏览 2 评论 0原文

Microsoft SQL Server 中存在一个表,其中包含记录 ID、开始日期、结束日期和数量。

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

假设存在包含所有可能日期的表,如何在 SQL Server 中生成如下例所示的结果集?

例如:

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 | 

对我可以获得的日期进行分组,然后获得当天的数量总和,但是由于用户提供的过滤器可能会排除其中一些记录,因此最终结果集无法聚合。

编辑

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

真实数据包含N条记录,每周增加,日期永远不会相同。可能有 2000 条具有不同开始日期和结束日期的记录...这就是我想要为其生成视图的内容。我可以直接加入数据来完成我需要的其余操作

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

A table exists in Microsoft SQL Server with record ID, Start Date, End Date and Quantity.

The idea is that for each record, the quantity/total days in range = daily quantity.

Given that a table containing all possible dates exists, how can I generate a result set in SQL Server to look like the following example?

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 | 

Grouping on dates I could get then get the sum of quantity on that day however the final result set can't be aggregate due to user provided filters that may exclude some of these records down the road.

EDIT

To clarify, this is just a sample. The filters are irrelevant as I can join to the side to pull in details related to the record ID in the results.

The real data contains N records which increases weekly, the dates are never the same. There could be 2000 records with different start and end dates... That is what I want to generate a view for. I can right join onto the data to do the rest of what I need

I should also mention this is for past, present and future data. I would love to get rid of a temporary table of dates. I was using a recursive query to get all dates that exist within a 50 year span but this exceeds MAXRECURSION limits for a view, that I cannot use.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

几味少女 2024-09-17 13:02:51

答案

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]

注意:下面的演示 CTE 使用 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

Answer

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]

NB: The below demo CTEs use the date datatype which is SQL Server 2008 the general approach should work for SQL2005 as well though.

Test Case

/*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]

Results

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
罗罗贝儿 2024-09-17 13:02:51

我想你可以试试这个。

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]

I think you can try this.

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]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文