简体   繁体   English

SQL工作日查询

[英]SQL working days query

I am trying to write a query to calculate the number of working days between 2 dates. 我正在尝试编写一个查询来计算两个日期之间的工作日数。 I first tried this in VBA, which worked, but this is not very efficient. 我首先在VBA中尝试了此方法,但效果很好,但这并不是很有效。

I have 2 queries, the first works out the date difference between a valueDate and cutOffDate; 我有2个查询,第一个查询计算出valueDate和cutOffDate之间的日期差; the second counts the number of dates from a table of holidays/weekends that fall between the valueDate and cutOffDay. 第二个秒则计算假日/周末表中介于valueDate和cutOffDay之间的日期数。

The trouble I'm having is how to combine these 2 parts to give the item age (number of working days between the dates). 我遇到的麻烦是如何结合这两个部分来确定项目的年龄(日期之间的工作日数)。

My query examples are: 我的查询示例是:

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

and

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

I need to subtract the result of the second query from the Age of the first query. 我需要从第一个查询的年龄中减去第二个查询的结果。

Sample input and output data 样本输入和输出数据

allOS: 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

Holidays: 假期:

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`

Result: 结果:

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

The results for age is the difference between the valueDate and cutOffDate less any of the days from the holiday table. 年龄的结果是valueDate和cutOffDate之间的差减去假日表中的任何一天。

You can use a correlated subquery to calculate the number of non-work days included in each valueDate and cutOffDate date range. 您可以使用相关子查询来计算每个valueDatecutOffDate日期范围中包含的非工作天数。

Here is a preliminary query I tested with your sample data, and I included the first and last rows output from that query. 这是我对您的样本数据进行测试的初步查询,并且包括了该查询输出的第一行和最后一行。

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

Notice the last row. 注意最后一行。 The raw_days value is zero because both valueDate and cutOffDate are the same. raw_days值为零,因为valueDatecutOffDate相同。 If you want that to be one day, add one to the value returned by the DateDiff expression. 如果希望这一天成为一天,则将其添加到DateDiff表达式返回的值中。

After you adjust that preliminary query as needed, you can use it as the data source for another query where you can calculate Age as raw_days - NonWorkDays . 在根据需要调整了该初步查询之后,可以将其用作另一个查询的数据源,您可以在其中将Age计算为raw_days - NonWorkDays But I'll leave that final piece for you in case I've botched the preliminary query. 但是,如果我对初步查询不满意,我将把最后的内容留给您。

If subqueries are unfamiliar to you, I recommend two of Allen Browne's pages for useful background information: Subquery basics and Surviving Subqueries . 如果您不熟悉子查询,建议您在Allen Browne的两个页面中获取有用的背景信息: 子查询基础知识生存子查询

Also note that correlated subqueries demand extra work from the db engine. 还要注意,相关子查询需要db引擎进行额外的工作。 That SELECT Count(*) subquery must be run separately for each row of the table. SELECT Count(*)子查询必须针对表的每一行分别运行。 You should have Holidays.holiday indexed to ease the db engine's burden. 您应该为Holidays.holiday编制索引,以减轻数据库引擎的负担。

It is easy, just read about with clause. 很简单,只需阅读with子句。 With it, you can run the first query and the second query then take the result and process it in the third query inside with clause 使用它,您可以运行第一个查询和第二个查询,然后获取结果并在with子句中的第三个查询中对其进行处理

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM