SQL - диапазон запросов между двумя датами (NON-VBA) - PullRequest
1 голос
/ 10 апреля 2010

Я вижу разные темы по переполнению стека, но ни одна из них не соответствует контексту MS-Access ...

Учитывая дату начала и дату окончания, существует ли способ через SQL возвращать записи за каждый данный месяц в течение периода времени?

EG:

A record has a Start Date of #1/1/2010# and an End Date of #1/31/2010#

Running the query against that single record, I would like the results to be
            #1/4/2010#   (Monday the 4th)
            #1/11/2010#  (Monday the 11th)
            #1/18/2010#   ...etc
            #1/25/2010#

Ограничения

  • MS-Access 2003: нет регистров / циклов внутри SQL (операторы IIF хороши)
  • Это только вид, НЕТ VBA будет использоваться, так как данные не будут изменены. Отключенный набор записей - мой последний вариант. Я бы предпочел выяснить, каким образом можно вызывать ваши настраиваемые функции в SQL, чтобы помочь вернуть эти значения ... некоторый класс, хранящийся в глобальной области видимости, пока вы итерируете этот диапазон дат, возможно ...

Возможно ли это? Я вижу много нет, но если бы был способ передать значение в функцию, я мог бы найти способ сделать эту работу. Грустно, что у меня нет способа симулировать хранимую процедуру без использования набора записей d / c, по крайней мере, я знаю ... какие-нибудь эксперты знают способ?

Ответы [ 4 ]

1 голос
/ 12 апреля 2010

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

Теперь, просто для удовольствия, вот очень уродливый, но полугибкий подход (использует таблицу с 10 записями и работает в диапазоне 273 лет)

Создайте таблицу с именем t10 с одним полем - id (сделайте ее длинным и первичным ключом) и введите десять строк: 0,1,2,3..9

После этого

SELECT #1/1/2010#+
       [t10].[ID]+
       [t100].[iD]*10+
       [t1000].[ID]*100+
       [t10000].[ID]*1000+
       [t100000].[iD]*10000 AS Mondays,
FROM t10, 
     t10 AS t100, 
     t10 AS t1000, 
     t10 AS t10000, 
     t10 AS t100000
WHERE  Weekday(#1/1/2010#+
               [t10].[ID]+
               [t100].[iD]*10+
               [t1000].[ID]*100+
               [t10000].[ID]*1000+  
               [t100000].[iD]*10000)=2;

возвращает все понедельники с 2010-1-1 по 2283-10-15 и не так медленно, как уродливо. Конечно, чтобы получить решение для вашего вопроса, вам нужно отфильтровать результаты для ваших полей date1 и date2.

По сути, это то же решение, что и временная таблица, с основным отличием в том, что вам не нужно перестраивать таблицу при каждом запросе.

Вы могли бы достичь того же результата только с одной таблицей с записями 0..99999, и если бы я использовал временные таблицы, я бы, вероятно, использовал что-то подобное.

1 голос
/ 10 апреля 2010

Вы можете создать гигантскую календарную таблицу с датами и днями в ней. 4/12/10, понедельник; 13.04.10, вторник и т. Д. Затем запросите эту гигантскую таблицу для получения результатов. Насколько большой диапазон в прошлом и будущем вам нужен? Несмотря на то, что это неуклюжее решение, оно, безусловно, сделает запросы простыми и понятными.

0 голосов
/ 13 апреля 2010

Надеюсь, я правильно понял ваш вопрос. Для этого нам нужно создать декартово произведение - поэтому вам следует создать еще одну таблицу. Для этого нужен только идентификатор с числами от 1 до наибольшего количества недель, которое будет содержаться в вашем диапазоне дат.

For example table: tCounter(CounterID int)
CounterID
1
2
3
4
etc..

для тестовых данных Я создал макет таблицы с вашими данными

For example: tDates(DateID int, startdate datetime, enddate datetime)
DateID, Startdate, EndDate
1,  1/1/10      1/31/10
2,  1/18/10     3/4/10
3,  2/1/10      2/28/10

оператор msaccess sql, который выдаст ваши результаты, выглядит как

SELECT tDates.DateID, ((7-Weekday([startdate],3))+[startdate])+(([CounterID]-1)*7) AS NewDay
FROM tDates, tCounter
WHERE (((((7-Weekday([startdate],3))+[startdate])+(([CounterID]-1)*7))<=[enddate]))
ORDER BY tDates.DateID, ((7-Weekday([startdate],3))+[startdate])+(([CounterID]-1)*7);

Если вы хотите изменить день с понедельника на другой день, измените аргумент в функции дня недели. 1=Sunday->7=Saturday

e.g. Weekday([startdate],3)...the 3=Tuesday so result is Monday 
e.g. Weekday([startdate],5)...the 5=Thursday so result is Wednesday 

Надеюсь, что это работает для вас.

0 голосов
/ 10 апреля 2010

Вы говорите о запросе, который генерирует несколько записей (по одной на дату) из одной записи. Я думаю, что это должно быть сделано с помощью хранимой процедуры (если ваша база данных SQL) или с помощью наборов записей. Ни один запрос не поможет. Создание набора записей и добавление записей, где это необходимо, кажется мне довольно простым. Вы должны пойти на это.

...