SQL工作日查询

时间:2013-11-20 08:34:15

标签: sql ms-access ms-access-2007

我正在尝试编写一个查询来计算两个日期之间的工作日数。我首先在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#]));   

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

示例输入和输出数据

ALLOS:

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之间的差异减去假期表中的任何天数。

2 个答案:

答案 0 :(得分:0)

您可以使用相关子查询来计算每个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 basicsSurviving Subqueries

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

答案 1 :(得分:-1)

这很容易,只需阅读with子句。 有了它,你可以运行第一个查询和第二个查询然后获取结果并在第三个查询里面用子句

处理它

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