SQL工作日查询

Posted

技术标签:

【中文标题】SQL工作日查询【英文标题】:SQL working days query 【发布时间】:2013-11-20 08:34:15 【问题描述】:

我正在尝试编写一个查询来计算两个日期之间的工作日数。我第一次在 VBA 中尝试过,效果很好,但是效率不高。

我有 2 个查询,第一个计算出 valueDate 和 cutOffDate 之间的日期差;第二个计算假期/周末表中介于 valueDate 和 cutOffDay 之间的日期数。

我遇到的麻烦是如何结合这两个部分来给出项目年龄(日期之间的工作日数)。

我的查询示例是:

SELECT allOS.SortCode, allOS.NPA, allOS.valueDate, allOS.cutOffDate, 
DateDiff("d",[allOS.valueDate],[allOS.cutOffDate]) AS Age
FROM allOS;

SELECT Count(Holidays.Holiday) AS NonWorkingDays 
FROM Holidays 
HAVING (([Holiday]>[#01/01/2013#] And [Holiday]<[#11/06/2013#]));   

我需要从第一个查询的年龄中减去第二个查询的结果。

样本输入和输出数据

所有操作系统:

sortCode|npa|valueDate|cutOffDate
111111|99999999|01-11-2013|15-11-2013
222222|77777777|04-11-2013|15-11-2013
333333|88888888|05-11-2013|15-11-2013
444444|66666666|06-11-2013|15-11-2013
555555|44444444|07-11-2013|15-11-2013
666666|33333333|12-11-2013|15-11-2013
777777|55555555|13-11-2013|15-11-2013
888888|11111111|14-11-2013|15-11-2013
999999|22222222|15-11-2013|15-11-2013

节假日:

holiday|reason
02-11-2013|Saturday
03-11-2013|Sunday
08-11-2013|Long Weekend
09-11-2013|Saturday
10-11-2013|Sunday
11-11-2013|Long Weekend
16-11-2013|Saturday
17-11-2013|Sunday`

结果:

sortCode|npa|valueDate|cutOffDate|Age
111111|99999999|01-11-2013|15-11-2013|8
222222|77777777|04-11-2013|15-11-2013|7
333333|88888888|05-11-2013|15-11-2013|6
444444|66666666|06-11-2013|15-11-2013|5
555555|44444444|07-11-2013|15-11-2013|4
666666|33333333|12-11-2013|15-11-2013|3
777777|55555555|13-11-2013|15-11-2013|2
888888|11111111|14-11-2013|15-11-2013|1
999999|22222222|15-11-2013|15-11-2013|0

年龄的结果是 valueDate 和 cutOffDate 之间的差减去假期表中的任何天数。

【问题讨论】:

【参考方案1】:

您可以使用相关子查询来计算每个 valueDatecutOffDate 日期范围中包含的非工作日数。

这是我使用您的示例数据测试的初步查询,我包含了该查询输出的第一行和最后一行。

SELECT
    a.sortCode,
    a.npa,
    a.valueDate,
    a.cutOffDate,
    DateDiff('d', a.valueDate, a.cutOffDate) AS raw_days,
    (
        SELECT Count(*)
        FROM Holidays
        WHERE holiday BETWEEN a.valueDate AND a.cutOffDate
    ) AS NonWorkDays
FROM allOS AS a;

sortCode npa      valueDate  cutOffDate raw_days NonWorkDays
-------- -------- ---------- ---------- -------- -----------
  111111 99999999  11/1/2013 11/15/2013       14           6
  999999 22222222 11/15/2013 11/15/2013        0           0

注意最后一行。 raw_days 的值为零,因为 valueDatecutOffDate 是相同的。如果您希望这一天为一天,请将 DateDiff 表达式返回的值加一。

根据需要调整初步查询后,您可以将其用作另一个查询的数据源,您可以将Age 计算为raw_days - NonWorkDays。但我会把最后的部分留给你,以防我把初步查询搞砸了。

如果您不熟悉子查询,我推荐 Allen Browne 的两个页面以获取有用的背景信息:Subquery basics 和 Surviving Subqueries。

还要注意,相关的子查询需要数据库引擎的额外工作。 SELECT Count(*) 子查询必须为表的每一行单独运行。您应该将Holidays.holiday 编入索引以减轻数据库引擎的负担。

【讨论】:

太棒了。首先,感谢您的所有帮助,其次,感谢您让我看到子查询的力量!我已经确定了他们可以帮助我的其他一些地方。我已经调整了以上内容以适应我的生产数据库,所以我非常高兴。下次我遇到困难并发布问题时,我一定会更仔细地考虑我在问什么,确保我提供尽可能多的信息。哦,也谢谢你的链接。这给了我更多阅读和实验的机会!【参考方案2】:

这很简单,只需阅读 with 子句。 有了它,您可以运行第一个查询和第二个查询,然后在 with 子句中的第三个查询中获取结果并处理它

http://www.oracle-base.com/articles/misc/with-clause.php

【讨论】:

我已经阅读了链接,但是我无法让它工作。这种事情不是我正常的日常工作,只是为了生病。 WITH 子句是否与 Access 2007 兼容?请原谅我,因为我不是一个有经验的 SQL 用户......不过我正在努力学习。

以上是关于SQL工作日查询的主要内容,如果未能解决你的问题,请参考以下文章

使用SQL语句如何对Excel工作表数据进行查询

SQL 计算 20 个工作日,删除银行存款并引用另一个查询

个人工作记录---工作中遇到的sql查询语句解析

如何在保存到 OneDrive 的 Excel 工作簿中运行 SQL 查询?

工作订单的递归 SQL Oracle 查询

Sql 查询无法正常工作