2013-11-20 3 views
1

Я пытаюсь написать запрос для расчета количества рабочих дней между двумя датами. Я сначала пробовал это в VBA, который работал, но это не очень эффективно.Запрос рабочих дней SQL

У меня есть 2 запроса, первое из них определяет разницу дат между valueDate и cutOffDate; второй подсчитывает количество дат из таблицы праздников/выходных дней, которые падают между valueDate и cutOffDay.

Проблема, с которой я столкнулся, состоит в том, как объединить эти 2 части, чтобы дать возраст предмета (количество рабочих дней между датами).

Мои примеры запросов являются:

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 меньше в любой день из праздничного стола.

ответ

0

Вы можете использовать коррелированный подзапрос для вычисления количества не- рабочие дни включены в каждый valueDate и cutOffDate диапазон дат.

Вот предварительный запрос, который я проверил с вашими данными примера, и я включил первый и последний строки, выводимые из этого запроса.

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 равно нулю, так как оба valueDate и cutOffDate являются одинаковыми. Если вы хотите, чтобы это было один день, добавьте его к значению, возвращаемому выражением DateDiff.

После того как вы отредактируете этот предварительный запрос по мере необходимости, вы можете использовать его в качестве источника данных для другого запроса, где вы можете вычислить Age как raw_days - NonWorkDays. Но я оставлю эту заключительную часть для вас на случай, если я испортил предварительный запрос.

Если подзапросы вам незнакомы, я рекомендую две страницы Аллена Брауна для получения полезной справочной информации: Subquery basics и Surviving Subqueries.

Также обратите внимание, что коррелированные подзапросы требуют дополнительной работы от движка db.Подзапрос SELECT Count(*) должен выполняться отдельно для каждой строки таблицы. Вы должны иметь индекс Holidays.holiday, чтобы облегчить нагрузку на двигатель db.

+1

блестящий. Спасибо, во-первых, за вашу помощь и, во-вторых, за то, что открыли мне глаза на подзапросы! Я уже определил несколько других мест, где они могли бы мне помочь. Я адаптировал это, чтобы соответствовать моей производственной базе данных, поэтому я не мог быть счастливее. В следующий раз, когда я застрял и поставил вопрос, я обязательно буду рассматривать то, что я прошу более тщательно, чтобы я предоставил как можно больше информации. О, спасибо за ссылки тоже. Это дало мне больше возможностей читать и экспериментировать! – sticks

-1

Это легко, просто прочитайте с предложением. С его помощью вы можете запустить первый запрос, а второй запрос затем принять результат и обработать его в третьем запросе внутри с пунктом

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

+0

Спасибо за указатель. Я посмотрю ссылку. – sticks

+0

У меня было прочитано по ссылке, однако я не смог заставить его работать. Это не моя нормальная дневная работа, просто покрывающая болезнь. Является ли предложение WITH совместимым с Access 2007? Пожалуйста, простите меня, поскольку я не являюсь опытным пользователем SQL ... пытаясь научиться. – sticks

Смежные вопросы