【问题标题】:SQL for Next/Prior Business Day from Calendar table (in MS Access)日历表中下一个/上一个工作日的 SQL(在 MS Access 中)
【发布时间】:2016-02-12 17:28:35
【问题描述】:

我从我们的大型机数据库中提取了一个日历表并保存为本地 Access 表。该表的历史可以追溯到 1930 年代(我知道我们至少在一个地方使用了 50 年代),产生了 31k 条记录。此日历表有 3 个感兴趣的字段:

Bus_Dt - 每天,而不仅仅是工作日。主键
Bus_Day_Ind - 指示当天是否是股票市场的有效工作日。
Pir_Bus_Dt - 前一个工作日。包含一些错误(大约 50 个),都是旧的。

我编写了一个查询来检索当前日历日或之后的第一个工作日,但它运行得非常慢。 (5 分钟以上)我检查了 showplan 输出,发现它是通过 x-join 运行的,它在 30k+ 记录表之间提供了大约 1000 万的解决方案空间(和日期比较)。不过,实际的任务并不难,只需简单的排序,Excel 就能在最短的时间内轻松完成。

因此,我的问题是,有没有办法解决查询性能不佳的问题,或者这是 SQL 的固有故障? (DB2 在大型机上运行也很慢,虽然不是很慢。在问题上抛出循环等等。)其次,如果我要信任 prir_bus_dt,我能做得更好吗?或者限制日期范围(又名“作弊”),或者我还没有想到的任何其他技巧?

SQL:

SELECT TE2Clndr.BUS_DT AS Cal_Dt  
    , Min(TE2Clndr_1.BUS_DT) AS Next_Bus_Dt  
FROM TE2Clndr  
    , TE2Clndr AS TE2Clndr_1  
WHERE TE2Clndr_1.BUS_DAY_IND="Y" AND  
    TE2Clndr.BUS_DT<=[te2clndr_1].[bus_dt]  
GROUP BY TE2Clndr.BUS_DT;

展示计划:

Inputs to Query  
Table 'TE2Clndr'  
Table 'TE2Clndr'
End inputs to Query
01) Restrict rows of table TE2Clndr
       by scanning
       testing expression "TE2Clndr_1.BUS_DAY_IND="Y""
       store result in temporary table
02) Inner Join table 'TE2Clndr' to result of '01)'
       using X-Prod join
       then test expression "TE2Clndr.BUS_DT<=[te2clndr_1].[bus_dt]"
03) Group result of '02)'

同样,问题是,这是否可以做得更好(更快),还是已经做到最好了?

【问题讨论】:

  • 由于您已将表导入 Access 并且该表不太可能经常刷新,您可以简单地添加一个 NEXT_BUS_DT 列,使用任何必要的方式填充它(即使它不是特别有效),然后直接查询“下一个营业日期”值。这也将有助于避免以后出现“查询必须使用可更新记录集”的问题。
  • 这是我在下面的“作弊”成功之前修复速度的默认计划。我尽量避免“制作表格”类型的执行,因为每个步骤都是一个可能被遗忘的项目——尤其是当它是一个每年只使用一次的步骤时。我也关心这个问题背后的“理论”,因为我有时在 DB2 服务器上使用相同的逻辑,而我没有表能力。 DB2 获得了正确的基本查询,但有时当它是较大任务中的子查询并因此产生糟糕的查询计划时会感到困惑。 (看不到来自 DB2 的计划,也被禁用了。)

标签: sql date ms-access


【解决方案1】:

我有一个新查询,对于同一个作业来说要快得多,但这取决于 pir_bus_dt 字段(它有一些错误)。这也不是很好的理论,因为前一个工作日不一定在每个人的日历上都可用。所以我不认为这个“答案”,只是一个答案。

新查询:

SELECT TE2Clndr.BUS_DT as Cal_Dt  
    , Max(TE2Clndr_1.BUS_DT) AS Next_Bus_Dt  
FROM TE2Clndr 
INNER JOIN TE2Clndr AS TE2Clndr_1
    ON TE2Clndr.PRIR_BUS_DT = TE2Clndr_1.PRIR_BUS_DT
GROUP BY TE2Clndr.BUS_DT;

【讨论】:

    【解决方案2】:

    这个方法怎么样

    select min(bus_dt)
    from te2Clndr
    where bus_dt >= date()
    and bus_day_ind = 'Y'
    

    This 是我的参考,date() 代表当前日期

    【讨论】:

    • 啊 - 我认为(正常情况下)我有点不清楚。我打算将其用作“翻译表”,以从其他地方获取日历日期列表并将其转换为适当的业务日期。所以我希望有一个列表,理论上,最多可以应用 30 个日期,而不仅仅是当前日期。您给了我一个想法,即仅在我实际需要的那些日期上运行日期逻辑,而不是构建整个翻译表,其中大部分在任何给定时间都不会使用。查询优化器甚至可以为我做这件事!
    • 我想象一个只有两个字段的翻译查询:[Calendar_Date] 和 [Next_Business_Date]。如果 Calendar_Date 是工作日,则这两个值相等。 (“下一个”有点误导,因为它可能仍然是同一天,但我没有更好的词来形容这个概念。)问题标题指的是如何将带有反转符号的相同查询用于前一个工作日以及下一个工作日。
    • @Et314159 - "'Next' 有点误导,因为它可能仍然是同一天,但我没有更好的词来形容这个概念。" - 我会建议您开始称其为“有效营业日期”。
    • @GordThompson 有效营业日期绝对是一个更好的名字。事实证明,我们经常需要返回而不是向前,因此一位同事建议“交易日期”(向前)和“报告日期”(向后)以避免任何(全局)歧义。我认为这个数据库只使用交易日期,但团队通常需要这两个概念。
    猜你喜欢
    • 2018-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-15
    • 1970-01-01
    • 1970-01-01
    • 2012-08-16
    • 1970-01-01
    相关资源
    最近更新 更多