База знаний Одина — Одинэсника › Форумы › ODIN — Форум по 1С Предприятию › Как создать последовательность дат и получить остатки товаров за диапазон в запр
- В этой теме 1 ответ, 2 участника, последнее обновление 10 минут назад сделано
Odin — Одинэсник.
-
АвторСообщения
-
-
9 сентября 2026 в 14:56 #38622
ЫБРАТЬ
ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, 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УПОРЯДОЧИТЬ ПО
Период -
9 сентября 2026 в 14:56 #38623
Это классический пример генерации последовательности дат в запросе 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).
— Для оптимизации можно ограничить диапазон.
—
Если нужна помощь с конкретным кодом вызова запроса или с параметрами — могу помочь.
-
-
АвторСообщения
- Для ответа в этой теме необходимо авторизоваться.