【问题标题】:Tricky Job with Date Ranges - MS Access/SQL日期范围的棘手工作 - MS Access/SQL
【发布时间】:2019-04-09 03:53:14
【问题描述】:

我有一项棘手的小工作要做,其中涉及计算某些日期范围之间的重叠。我在 VBA/Excel 中编写了一些代码,效果很好,但是速度慢得惊人——而且我认为这种东西属于 Access(或类似的)而不是 Excel。

对需要做什么的非常简短的总结......

有一个看起来像这样的主表(可能是数百万行):

Main_Table

  • Account_Number_Index
  • 开始日期
  • 结束日期
  • Data_Item_1
  • Data_Item_2 ... ... ...
  • Data_Item_N

我还有一个“分析周期”的小表格(通常只有 4-6 行)

Analysis_Periods

  • Period_Index
  • Period_Start_Date
  • Period_End_Date
  • Period_Label

我需要根据所有这些创建一个输出表,其中每个 Account_Number_Index 和 Period_Index 组合都有一条记录。字段将是:

输出表

  • Account_Number_Index
  • Overlap_Start_Date(如下所述)
  • Overlap_End_Date(解释如下)
  • Period_Index
  • Period_Lable
  • Data_Item_1
  • Data_Item_2 ... ... ...
  • Data_Item_N

所以在松散的伪代码中它看起来像这样:

For each row in Main_Table

    For each row in Analysis_Periods

        Work out the overlapping period (Overlap_Start_Date...Overlap_End_Date) for time intervals (Start_Date...End_Date) and (Period_Start_Date...Period_End_Date)

        If there is no overlap at all

            Do nothing

        Else

            Output a row of data to Output_Table which is identical to the row in the Main_Table except that:
                 * Overlap_Start_Date used instead of Start_Date
                 * Overlap_End_Date used instead of End_Date
                 * Period_Index and Period_Label tagged also output

         End If

    Next row in Analysis_Periods

Next row in Main_Table

计算重叠期只是以下时间间隔的一个例子: (a) max(Start_Date, Period_Start_Date) (b) min(End_Date, Period_End_Date)

我想我已经设法在下面包含一个超链接,以便在一张纸上写下一点 re:重叠时间间隔,如果这有助于可视化问题。

谁能建议一种在 Access 中执行此操作的有效方法,使用一些 SQL 代码或一些 VBA(或两者)?

我不是这方面的专家,所以我希望我是有道理的......如果不是,请道歉。

非常感谢您的帮助。

谢谢 一个

https://i.stack.imgur.com/Al3pO.jpg

【问题讨论】:

  • 分析和周期索引对可以有多个重叠的日期范围吗?

标签: sql date ms-access


【解决方案1】:

考虑在两个表之间过滤CROSS JOIN,您将表放在FROM 子句中的逗号分隔列表中,没有任何JOIN,后跟WHERE 日期。然后将查询放在条件聚合 GROUP BY 中,以获取所需的 MINMAX 日期。

SELECT m.Account_Number_Index, 
       p.Period_Index, 
       MIN(IIF(m.Start_Date < a.Period_Start_Date, 
               m.Start_Date, a.Period_Start_Date)) AS Overlap_Start_Date,
       MAX(IIF(m.End_Date < a.Period_End_Date, 
               a.Period_End_Date, m.End_Date)) As Overlap_End_Date

FROM MainTable m, AnalysisPeriods a
WHERE m.Start_Date <= a.Period_Start_Date 
  AND a.Period_End_Date <= m.End_Date
GROUP BY m.Account_Number_Index, 
         p.Period_Index

然后在第二个查询中将原始表连接到索引字段上的此查询。甚至可以考虑构建一个临时表overlap_table(带有SELECT ... INTO 子句)并用于代替查询:

SELECT m.Account_Number_Index, 
       p.Period_Index, 
       q.Overlap_Start_Date, 
       q.Overlap_End_Date
       p.Period_Label,
       m.Data_Item_1,
       m.Data_Item_2,
       m.Data_Item_3, 
       ...
       m.Data_Item_n

FROM (overlap_query_or_table q
INNER JOIN MainTable m 
  ON q.Account_Number_Index = m.Account_Number_Index)
INNER JOIN AnalysisPeriods a
  ON q.Period_Index = p.Period_Index

注意:此处理涉及交叉连接,它返回两个表之间的笛卡尔积(即约 100 万行 X 5-6 行),因此无法保证效率。

【讨论】:

  • 感谢两位的建议。我已经能够使用 Access 中的表达式生成器创建交叉连接(直到昨晚我才听说过交叉连接!)。我应该能够调整查询以对新大表中的每一行进行时间重叠计算,我想我会完成的。
  • 那么这个答案是否有效?有什么错误吗?不想要的结果?从技术上讲,这不是真正的交叉连接,因为我们使用了 WHEREGROUP BY
【解决方案2】:

如果使用访问,为什么不使用连接查询? 有点像

Select m.Account_Number_Index, m.Start_Date,m.End_Date, ap.Period_Index, ap.Period_Lable,
m.Data_Item_1, m.Data_Item_2 ... ... ... m.Data_Item_N
From Analysis_Periods as ap left join Main_Table as m on (m.Start_Date >= ap.Period_Start_Date and m.End_date <= ap.Period_End_Date)

对于正确的重叠开始和结束使用函数 iif。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 2022-11-10
    相关资源
    最近更新 更多