Как создать последовательность дат и получить остатки товаров за диапазон в запр

База знаний Одина — Одинэсника Форумы ODIN — Форум по 1С Предприятию Как создать последовательность дат и получить остатки товаров за диапазон в запр

Просмотр 1 ветки ответов
  • Автор
    Сообщения
    • #38622
      Фото аватараOdineski
      Участник

        ЫБРАТЬ
        ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, aa.a * 1000 + bb.b * 100 + cc.c * 10 + dd.d) КАК Период
        ПОМЕСТИТЬ ВТ_ТабДат
        ИЗ
        (ВЫБРАТЬ
        0 КАК a

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        1

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        2

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        3

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        4

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        5

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        6

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        7

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        8

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        9) КАК aa
        ПОЛНОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
        0 КАК b

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        1

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        2

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        3

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        4

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        5

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        6

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        7

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        8

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        9) КАК bb
        ПО (ИСТИНА)
        ПОЛНОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
        0 КАК c

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        1

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        2

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        3

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        4

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        5

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        6

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        7

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        8

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        9) КАК cc
        ПО (ИСТИНА)
        ПОЛНОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
        0 КАК d

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        1

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        2

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        3

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        4

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        5

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        6

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        7

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        8

        ОБЪЕДИНИТЬ

        ВЫБРАТЬ
        9) КАК dd
        ПО (ИСТИНА)
        ГДЕ
        aa.a * 1000 + bb.b * 100 + cc.c * 10 + dd.d <= РАЗНОСТЬДАТ(&НачалоПериода, &КонецПериода, ДЕНЬ)
        ;

        ////////////////////////////////////////////////////////////////////////////////
        ВЫБРАТЬ
        Номенклатура.Ссылка КАК Номенклатура
        ПОМЕСТИТЬ ВТ_ТабТоваров
        ИЗ
        Справочник.Номенклатура КАК Номенклатура
        ГДЕ
        НЕ Номенклатура.ЭтоГруппа
        И НЕ Номенклатура.ПометкаУдаления
        И Номенклатура.ВидНоменклатуры.Наименование ПОДОБНО «%Товар%»
        И Номенклатура.Ссылка В ИЕРАРХИИ(&ПарамОтборТовар)
        ;

        ////////////////////////////////////////////////////////////////////////////////
        ВЫБРАТЬ
        ВТ_ТабДат.Период,
        ВТ_ТабТоваров.Номенклатура
        ПОМЕСТИТЬ ВТ_ТабДатТоваров
        ИЗ
        ВТ_ТабДат КАК ВТ_ТабДат,
        ВТ_ТабТоваров КАК ВТ_ТабТоваров
        ;

        ////////////////////////////////////////////////////////////////////////////////
        ВЫБРАТЬ
        ВТ_ТабДатТоваров.Номенклатура,
        ВТ_ТабДатТоваров.Период,
        МАКСИМУМ(ОстаткиТоваровОстаткиИОбороты.Период) КАК ПериодРегистра
        ПОМЕСТИТЬ ВТ_ТабМаксимальныхПериодов
        ИЗ
        ВТ_ТабДатТоваров КАК ВТ_ТабДатТоваров
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, День, , ) КАК ОстаткиТоваровОстаткиИОбороты
        ПО ВТ_ТабДатТоваров.Номенклатура = ОстаткиТоваровОстаткиИОбороты.Номенклатура
        И ВТ_ТабДатТоваров.Период >= ОстаткиТоваровОстаткиИОбороты.Период

        СГРУППИРОВАТЬ ПО
        ВТ_ТабДатТоваров.Номенклатура,
        ВТ_ТабДатТоваров.Период
        ;

        ////////////////////////////////////////////////////////////////////////////////
        ВЫБРАТЬ РАЗЛИЧНЫЕ
        ВТ_ТабМаксимальныхПериодов.Номенклатура,
        ВТ_ТабМаксимальныхПериодов.Период КАК Период,
        ОстаткиТоваровОстаткиИОбороты.КоличествоКонечныйОстаток КАК Остатки
        ИЗ
        ВТ_ТабМаксимальныхПериодов КАК ВТ_ТабМаксимальныхПериодов
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, День, , ) КАК ОстаткиТоваровОстаткиИОбороты
        ПО ВТ_ТабМаксимальныхПериодов.ПериодРегистра = ОстаткиТоваровОстаткиИОбороты.Период
        И ВТ_ТабМаксимальныхПериодов.Номенклатура = ОстаткиТоваровОстаткиИОбороты.Номенклатура
        ГДЕ
        НЕ ОстаткиТоваровОстаткиИОбороты.КоличествоКонечныйОстаток ЕСТЬ NULL
        И НЕ ОстаткиТоваровОстаткиИОбороты.КоличествоКонечныйОстаток = 0

        УПОРЯДОЧИТЬ ПО
        Период

      • #38623
        bot_avaOdin — Одинэсник
        Участник

          Это классический пример генерации последовательности дат в запросе 1С с помощью декартова произведения цифр 0..9, чтобы получить диапазон дней от &НачалоПериода до &КонецПериода.

          Разбор и рекомендации:

          1. Генерация дат

          |ВЫБРАТЬ
          | ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, aa.a * 1000 + bb.b * 100 + cc.c * 10 + dd.d) КАК Период
          |ПОМЕСТИТЬ ВТ_ТабДат
          |ИЗ
          | (ВЫБРАТЬ 0 КАК a ОБЪЕДИНИТЬ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ … ВЫБРАТЬ 9) КАК aa
          | ПОЛНОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ 0 КАК b ОБЪЕДИНИТЬ … ВЫБРАТЬ 9) КАК bb ПО ИСТИНА
          | ПОЛНОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ 0 КАК c ОБЪЕДИНИТЬ … ВЫБРАТЬ 9) КАК cc ПО ИСТИНА
          | ПОЛНОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ 0 КАК d ОБЪЕДИНИТЬ … ВЫБРАТЬ 9) КАК dd ПО ИСТИНА
          |ГДЕ
          | aa.a * 1000 + bb.b * 100 + cc.c * 10 + dd.d <= РАЗНОСТЬДАТ(&НачалоПериода, &КонецПериода, ДЕНЬ)

          — Здесь создается последовательность чисел от 0 до максимального количества дней между датами.

          — Для каждого числа прибавляется к &НачалоПериода, получается последовательность дат.

          2. Формирование списка товаров

          |ВЫБРАТЬ
          | Номенклатура.Ссылка КАК Номенклатура
          |ПОМЕСТИТЬ ВТ_ТабТоваров
          |ИЗ
          | Справочник.Номенклатура КАК Номенклатура
          |ГДЕ
          | НЕ Номенклатура.ЭтоГруппа
          | И НЕ Номенклатура.ПометкаУдаления
          | И Номенклатура.ВидНоменклатуры.Наименование ПОДОБНО «%Товар%»
          | И Номенклатура.Ссылка В ИЕРАРХИИ(&ПарамОтборТовар)

          — Отбор товаров по иерархии и по виду.

          3. Декартово произведение дат и товаров

          |ВЫБРАТЬ
          | ВТ_ТабДат.Период,
          | ВТ_ТабТоваров.Номенклатура
          |ПОМЕСТИТЬ ВТ_ТабДатТоваров
          |ИЗ
          | ВТ_ТабДат КАК ВТ_ТабДат,
          | ВТ_ТабТоваров КАК ВТ_ТабТоваров

          — Получаем все сочетания дат и товаров.

          4. Определение максимального периода в регистре для каждой пары (товар, дата)

          |ВЫБРАТЬ
          | ВТ_ТабДатТоваров.Номенклатура,
          | ВТ_ТабДатТоваров.Период,
          | МАКСИМУМ(ОстаткиТоваровОстаткиИОбороты.Период) КАК ПериодРегистра
          |ПОМЕСТИТЬ ВТ_ТабМаксимальныхПериодов
          |ИЗ
          | ВТ_ТабДатТоваров КАК ВТ_ТабДатТоваров
          | ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, День, , ) КАК ОстаткиТоваровОстаткиИОбороты
          | ПО ВТ_ТабДатТоваров.Номенклатура = ОстаткиТоваровОстаткиИОбороты.Номенклатура
          | И ВТ_ТабДатТоваров.Период >= ОстаткиТоваровОстаткиИОбороты.Период
          |СГРУППИРОВАТЬ ПО
          | ВТ_ТабДатТоваров.Номенклатура,
          | ВТ_ТабДатТоваров.Период

          — Для каждой даты и товара ищется максимальная дата из регистра, не превышающая текущую дату.

          5. Получение остатков по найденным периодам

          |ВЫБРАТЬ РАЗЛИЧНЫЕ
          | ВТ_ТабМаксимальныхПериодов.Номенклатура,
          | ВТ_ТабМаксимальныхПериодов.Период КАК Период,
          | ОстаткиТоваровОстаткиИОбороты.КоличествоКонечныйОстаток КАК Остатки
          |ИЗ
          | ВТ_ТабМаксимальныхПериодов КАК ВТ_ТабМаксимальныхПериодов
          | ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, День, , ) КАК ОстаткиТоваровОстаткиИОбороты
          | ПО ВТ_ТабМаксимальныхПериодов.ПериодРегистра = ОстаткиТоваровОстаткиИОбороты.Период
          | И ВТ_ТабМаксимальныхПериодов.Номенклатура = ОстаткиТоваровОстаткиИОбороты.Номенклатура
          |ГДЕ
          | НЕ ОстаткиТоваровОстаткиИОбороты.КоличествоКонечныйОстаток ЕСТЬ NULL
          | И НЕ ОстаткиТоваровОстаткиИОбороты.КоличествоКонечныйОстаток = 0
          |УПОРЯДОЧИТЬ ПО
          | Период

          Рекомендации:

          — Параметры &НачалоПериода, &КонецПериода должны быть типа Дата.

          — Параметр &ПарамОтборТовар — ссылка на элемент справочника или таблица значений с элементами справочника.

          — Если период большой (больше 9999 дней), генерация дат может быть очень тяжелой. Обычно хватает 3-4 цифр (aa, bb, cc).

          — Для оптимизации можно ограничить диапазон.

          Если нужна помощь с конкретным кодом вызова запроса или с параметрами — могу помочь.

      Просмотр 1 ветки ответов
      • Для ответа в этой теме необходимо авторизоваться.
      База знаний 1С