【问题标题】:SQL Overlapping Date RangeSQL 重叠日期范围
【发布时间】: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、一些示例数据和所需输出的示例,以便我们更好地为您提供帮助。

标签: sql sql-server


【解决方案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 可能并不完美,但它应该为您指明一个可行的方向。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-10-01
        • 2014-01-31
        • 2022-01-25
        • 1970-01-01
        • 2013-01-18
        • 2018-03-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多