SQL 重叠日期范围
Posted
技术标签:
【中文标题】SQL 重叠日期范围【英文标题】:SQL Overlapping Date Range 【发布时间】:2013-07-17 19:24:32 【问题描述】:我有一个包含 3 个字段“开始日期”和“结束日期”以及“分配百分比”的表格。我将需要找出该表中从当前日期起 3 个月内的所有记录,
而且(这个很棘手)只有 Sum(Allocation %) > 100 的日期范围重叠的记录。
请帮我提出一个问题。
这是表架构。
Table (ResourceAssignment)
- ResourceAssignmentID (PK)
- ResourceID (FK)
- Assigned To (FK)
- Start Date
- End Date
- Allocation %
我基本上需要在一定时期内(从当天到3个月)找到全部分配的资源。
提前致谢!
【问题讨论】:
重叠的日期范围是什么意思?您是指开始或结束日期在当前日期后 3 个月内的任何记录吗? 请将您的架构添加到sqlfiddle.com、一些示例数据和所需输出的示例,以便我们更好地为您提供帮助。 【参考方案1】:不确定这是否是您所追求的,但这会向您显示分配高于 100% 的所有 ResourceID,其开始或结束日期在过去 3 个月内:
SELECT ResourceID
FROM ResourceAssignment
WHERE StartDate BETWEEN DATEADD(month,-3,GETDATE()) AND GETDATE()
OR EndDate BETWEEN DATEADD(month,-3,GETDATE()) AND GETDATE()
GROUP BY ResourceID
HAVING SUM([Allocation %]) > 100
【讨论】:
好点,不清楚哪个领域属于那里,但显然不是PK。 如果结果中需要包含“open assignments”,将WHERE子句的第二部分修改如下:OR ( (EndDate IS NULL) OR (EndDate BETWEEN DATEADD(month,-3,GETDATE()) AND GETDATE()))
如果您在 1 月 1 日至 1 月 15 日分配了 80% 的资源,并且在 1 月 16 日至 1 月 31 日分配了 85% 的资源,则此查询将说它在 165% 时过度分配。这并不能回答过度分配 重叠 范围的问题。
是的,我要求澄清 OP 所说的重叠是什么意思,因为问题不清楚。【参考方案2】:
您有两种通用解决方案。哪个最好取决于 ResourceAllocation 的大小、冲突的频率以及您打算如何呈现数据。
解决方案 1:列出未来 3 个月内的日期并与之对照,以确定哪些日期被过度分配
WITH
datelist AS (
SELECT CAST(GETDATE() AS date) [d] UNION ALL SELECT DATEADD(day,1,[d]) FROM datelist WHERE [d] < DATEADD(month,3,GETDATE())
),
allocations AS (
SELECT *,SUM([Allocation %]) OVER(PARTITION BY [ResourceID],[d]) AS [Total Allocation %]
FROM datelist
INNER JOIN ResourceAssignment ON ([d] BETWEEN [Start Date] AND [End Date])
)
SELECT *
FROM allocations
WHERE [Total Allocation %] >= 100
解决方案 2:在 ResourceAssignment 上使用具有自联接的范围冲突查询
SELECT *
FROM (
SELECT
t1.*,SUM(t1.[Allocation %]) OVER(PARTITION BY t1.[ResourceID]) AS [Total Allocation %]
FROM ResourceAssignment t1
INNER JOIN ResourceAssignment t2 ON (
t1.[ResourceID] = t2.[ResourceID] AND
t1.[ResourceAssignmentID] <> t2.[ResourceAssignmentID] AND
t1.[Start Date] < t2.[End Date] AND
t2.[Start Date] < t1.[End Date]
)
WHERE
t1.[Start Date] <= CAST(GETDATE()+30 as date) AND
t2.[Start Date] <= CAST(GETDATE()+30 as date) AND
t1.[End Date] > CAST(GETDATE() as date) AND
t2.[End Date] > CAST(GETDATE() as date)
) t
WHERE [Total Allocation %] >= 100
【讨论】:
【参考方案3】:我认为这就是你想要达到的目标:
SELECT SUM(Allocation), ResourceID
FROM ResourceAssignment
WHERE EndDate BETWEEN GETDATE() AND DATEADD(m,3,GETDATE())
GROUP BY ResourceID
HAVING SUM(Allocation) > 100
【讨论】:
【参考方案4】:我假设开始日期和结束日期被格式化为日期时间或日期。
我不确定您是在尝试确定开始日期记录是在过去 3 个月内还是结束日期记录内。
您还需要一个限制来确定总和(分配百分比)。你想总结什么独特的记录。由于您想对分配百分比求和,然后只选择大于 100 的那些,因此您必须弄清楚要拉出哪些然后求和。
您需要使用 With 语句或创建分阶段提取所需信息的子“表”(查询)来完成此操作。我将介绍子查询语句。
为 Sql-Server 2008 R2 编写
首先选择过去 3 个月内的数据
Select ResourceAssignmentID, ResourceID, [Assigned To], [Allocation %]
From ResourceAssignment
Where [Start Date] >= dateadd(Month,-3,Now)
然后使用此数据对分配百分比求和。 (我假设基于 2 个外键的组合)
Select Query1.ResourceID, Query1.[Assigned To], sum(Query1.[Allocation %]) as Sumofallocation
From
(Select ResourceAssignmentID, ResourceID, [Assigned To], [Allocation %]
From ResourceAssignment
Where [Start Date] >= dateadd(Month,-3,Now)) Query1
Group By Query1.ResourceID, Query1.[Assigned To], sum(Query1.[Allocation %])
您可以在 group by 之前添加 Where 语句以过滤出您 >100 的要求,但我只需添加另一个 Select 语句即可将它们全部组合在一起
Select * From
(Select Query1.ResourceID, Query1.[Assigned To], sum(Query1.[Allocation %]) as Sumofallocation
From
(Select ResourceAssignmentID, ResourceID, [Assigned To], [Allocation %]
From ResourceAssignment
Where [Start Date] >= dateadd(Month,-3,Now)) Query1
Group By Query1.ResourceID, Query1.[Assigned To], sum(Query1.[Allocation %])
) Query2
Where Query2.Sumofallocation > 100
此外,您似乎正在从事项目管理类型的程序。微软项目不会工作吗?您将能够在您希望的任何时间范围内查看谁被过度分配。如果您有多个项目,您可以将它们合并到一个大的项目文件中并以这种方式查看...
无论如何,我希望这会有所帮助。 SQL 可能并不完美,但它应该为您指明一个可行的方向。
【讨论】:
以上是关于SQL 重叠日期范围的主要内容,如果未能解决你的问题,请参考以下文章