Список дат произвольного месяца в запросе

Для разворачивания остатков/приходов/расходов на каждую дату месяца, в запросе, требуется как минимум список дат месяца по которому будут развернуты данные

Для разворачивания остатков/приходов/расходов на каждую дату месяца в запросе требуется как минимум список дат месяца. Порывшись в интернете я нашел советы использовать для этого: а) РегистрСведений.КурсыВалют (не айс решение) б)РегистрСведений.РегламентированныйПроизводственный1Календарь (уже лучше, если он у Вас есть в конфигурации) в)заполнить список в цикле и подтянуть его в запрос (тривиально довольно) Мое решение самому создать список дат в запросе: 

ВЫБРАТЬ
таб.Даты
ИЗ
(ВЫБРАТЬ
НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ) КАК Даты
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 1)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 2)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 3)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 4)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 5)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 6)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 7)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 8)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 9)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 10)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 11)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 12)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 13)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 14)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 15)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 16)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 17)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 18)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 19)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 20)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 21)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 22)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 23)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 24)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 25)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 26)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 27)
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ВЫБОР
КОГДА ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 28) > КОНЕЦПЕРИОДА(&дат1, МЕСЯЦ)
ТОГДА ДАТАВРЕМЯ(1, 1, 1)
ИНАЧЕ ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 28)
КОНЕЦ
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ВЫБОР
КОГДА ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 29) > КОНЕЦПЕРИОДА(&дат1, МЕСЯЦ)
ТОГДА ДАТАВРЕМЯ(1, 1, 1)
ИНАЧЕ ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 29)
КОНЕЦ
ОБЪЕДИНИТЬ
ВЫБРАТЬ
ВЫБОР
КОГДА ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 30) > КОНЕЦПЕРИОДА(&дат1, МЕСЯЦ)
ТОГДА ДАТАВРЕМЯ(1, 1, 1)
ИНАЧЕ ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 30)
КОНЕЦ) КАК таб
ГДЕ
таб.Даты <> ДАТАВРЕМЯ(1, 1, 1)

Можно было бы и по короче (выкинув средину), но большинству будет удобней просто скопировать в КонсольЗапросов код запроса. От сюда не далеко до списка за интервал дат месяца, за несколько месяцев. Предлагаю обсудить возможность более компактного построения запроса и другие способы получения списка дат в запросе. 

Яремчук Константин

19 Comments

  1. Serj1C

    Запрос в (0) совсем длинный…

    надо как-то так

    ВЫБРАТЬ 0 КАК А ПОМЕСТИТЬ Ц
    ОБЪЕДИНИТЬ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВЫБРАТЬ 3
    ОБЪЕДИНИТЬ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВЫБРАТЬ 6;
    
    ////////////////////////////////////////////////////////////­////////////////////
    ВЫБРАТЬ
    ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, ц1.А * 6 + ц2.А) КАК ДниМесяца
    ИЗ
    Ц КАК ц1,
    Ц КАК ц2
    ГДЕ
    ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, ц1.А * 6 + ц2.А) < КОНЕЦПЕРИОДА(&дат1, МЕСЯЦ)

    Показать

    Reply
  2. wunderland

    Тоже вариант, я как-то с єтим парился, но остановился на «заполнить в цикле»

    Reply
  3. tango

    вредная публикация

    изучайте СКД, глубоко не надо

    Reply
  4. andrewks

    жесть какая-то. или порождающий запрос по типу (1), или соединение с произв.календарём, или СКД.

    Reply
  5. nucha

    (3) tango, без примера это пустые слова. Типа: я знаю как, но вам не скажу. Даже для СКД нет примера. А просто в запросе слабо?

    Reply
  6. nucha

    (4) andrewks, пустые слова как у tango. Произвольный календарь в запросе? ну, ну…

    Reply
  7. Serj1C

    поддерживаю мысль (3), что публикация вредная и вообще не публикация..

    Reply
  8. nucha

    1.Ваш код для любого полного месяца в 31 день будет точно таким же длинным т.к. в месяце более 6 дней.

    2.В данном случае применение виртуальной таблицы только увеличило время выполнения кода с 0,005433 до 0,005635

    и ни чего более.

    Публикация создана как пример решения данной задачи, а пока один флуд..

    Reply
  9. andrewks

    (6) nucha, не произвольный, а производственный. учите матчасть

    Reply
  10. andrewks

    (8)

    Ваш код для любого полного месяца в 31 день будет точно таким же длинным т.к. в месяце более 6 дней

    бред.

    В данном случае применение виртуальной таблицы только увеличило время выполнения кода с 0,005433 до 0,005635

    и ни чего более

    о да, две десятитысячных — это очень крутое достижение. особенно для 1С

    Reply
  11. andrewks

    вот пример решения на основе порождающего запроса:

    select
    0 as num
    into digits
    union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9
    
    ;
    
    select
    dateadd(&LeftBound,day,digits1.num+10*digits2.num+100*digits3.num+1000*digits4.num) as Дата
    from
    digits as digits1
    ,digits as digits2
    ,digits as digits3
    ,digits as digits4
    where (dateadd(&LeftBound,day,digits1.num+10*digits2.num+100*digits3.num+1000*digits4.num)<=&RightBound)
    order by Дата
    
    

    Показать

    в LeftBound и RightBound задаётся диапазон дат, в результате получаем все даты из заданного диапазона.

    Reply
  12. nucha

    (11) andrewks, тоже самое, что у меня, только другими словами и в худшем, чем у меня варианте.

    Читайте внимательно: пример дан для случаев когда нет произв.календаря. В месяце больше 6 дней, что тут бредового и у кого бред? Суть не только в скорости работы запроса, а в неумелом применении виртуальной таблицы. Пример в (11) в файловом варианте бред.

    Reply
  13. petrov_al

    Вот запрос, идея взята у Гилева:

    ВЫБРАТЬ

    1 КАК цифра

    ПОМЕСТИТЬ вт

    ОБЪЕДИНИТЬ ВСЕ

    ВЫБРАТЬ

    2

    ОБЪЕДИНИТЬ ВСЕ

    ВЫБРАТЬ

    3

    ОБЪЕДИНИТЬ ВСЕ

    ВЫБРАТЬ

    4

    ОБЪЕДИНИТЬ ВСЕ

    ВЫБРАТЬ

    5

    ОБЪЕДИНИТЬ ВСЕ

    ВЫБРАТЬ

    6

    ОБЪЕДИНИТЬ ВСЕ

    ВЫБРАТЬ

    7

    ОБЪЕДИНИТЬ ВСЕ

    ВЫБРАТЬ

    8

    ;

    ////////////////////////////////////////////////////////////­////////////////////

    ВЫБРАТЬ

    (вт.цифра — 1) * 8 * 8 * 8 + (вт1.цифра — 1) * 8 * 8 + (вт2.цифра — 1) * 8 + вт3.цифра КАК цифра,

    ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(2010, 1, 1), ДЕНЬ, (вт.цифра — 1) * 8 * 8 * 8 + (вт1.цифра — 1) * 8 * 8 + (вт2.цифра — 1) * 8 + вт3.цифра — 1) КАК даты

    ИЗ

    вт КАК вт,

    вт КАК вт1,

    вт КАК вт2,

    вт КАК вт3

    ГДЕ

    ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(2010, 1, 1), ДЕНЬ, (вт.цифра — 1) * 8 * 8 * 8 + (вт1.цифра — 1) * 8 * 8 + (вт2.цифра — 1) * 8 + вт3.цифра — 1) < ДАТАВРЕМЯ(2011, 1, 1)

    Reply
  14. andrewks

    (12) nucha, в моём примере вообще нет виртуальных таблиц. и в файловом варианте всё замечательно работает. может, стоит теорию маленько подучить, да проверить на практике, прежде, чем вступать в дискуссии?

    в худшем, чем у меня варианте

    ну, это я вообще оставлю без комментариев. всяк кулик имеет право хвалить своё болото.

    Reply
  15. andrewks

    (13) petrov_al, восьмеричная система? прикольно

    Reply
  16. catena

    Как минимум можно заменить хвост запроса:

    Код
       ВЫБРАТЬ
          ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 28)
       ОБЪЕДИНИТЬ
       ВЫБРАТЬ
          ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 29)
       ОБЪЕДИНИТЬ
       ВЫБРАТЬ
          ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&дат1, МЕСЯЦ), ДЕНЬ, 30)) КАК таб
    ГДЕ
       таб.Даты между НачалоПериода(&дат1,Месяц) и КонецПериода(&дат1,Месяц)

    Показать полностью

    И короче и быстрее будет.

    Reply
  17. absolutblohin

    Самое ужасное что со мной произошло на этой неделе — то что я увидел эту публикацию. Даже вчерашнее посещение стоматолога прошло более приятно.

    Reply
  18. shuhorov

    (17) absolutblohin,

    до конца недели еще оого сколько времени

    Reply
  19. nucha

    (16) catena, так действительно красивее и короче и быстрее (пардон за рифму).

    (17) тема не страшнее Вашего аватара и не хуже Ваших публикаций.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *