Получение данных для партионного списания запросом

20.03.14

Разработка - Запросы

Всегда, когда заглядываю в шпаргалки моментально вспоминаю весь алгоритм построения запроса для партионного списания. И я не про запрос, который просто получает остатки из регистра партий товаров, а про запрос, который получает таблицу которую можно просто загрузить в движения, то есть рассчитывает какие партии должны списаться, сколько с партии списать товаров и какая стоимость списания каждой партии в итоге должна быть получена. Последний раз не хорошо получилось перед группой - я сдался и не дописал запрос. Исправляюсь, теперь у меня будет шпаргалка в виде статьи ;) Надеюсь, пригодится не только мне.

Исходная конфигурация

Конфигурация примитивная. два документа с классическим составом и регистр накопления остатков. Партия в регистре - это ссылка на документ “ПриходнаяНакладная”. Остальное, надеюсь, очевидно.

В тестовой конфигурации были проведены “Приходные”, для формирования остатков по партиям.

Примечание

Да, статья исключительно академическая, в реальной эксплуатации сомнительно применение подобного подхода.

Да - нет контроля остатков.

Да - только метод FIFO. Если есть вопрос как реализовать это методом LIFO - то повторное прочтение статьи Вам вряд ли поможет, как собственно и сама статья - вряд ли будет для Вас полезной.

Да - все можно свести к 3 запросам в пакете и не плодить кучу временных таблиц. Да - можно, я расписал подробно для пущего понимания.

Поехали

Я буду очень подробно показывать получение данных. Прямо по шагам.

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

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

СГРУППИРОВАТЬ ПО
   Товар
ИНДЕКСИРОВАТЬ ПО
   Товар

Из документа нам нужно только количество и сам товар. На всякий случай данные сгруппируем и поместим все во временную таблицу.

Получим остатки партий

Далее выберем остатки из регистра с отбором по товарам из таблицы документа.

ВЫБРАТЬ
   Товар,
   Партия,
   Партия.МоментВремени КАК МоментВремени,
   КоличествоОстаток,
   СтоимостьОстаток
ПОМЕСТИТЬ Остатки
ИЗ
   РегистрНакопления.ПартииТоваров.Остатки(
           ,
           Товар В
               (ВЫБРАТЬ
                   ДокТЧ.Товар
               ИЗ
                   ДокТЧ КАК ДокТЧ))

ИНДЕКСИРОВАТЬ ПО
   Товар

Итого получили 2 временные таблицы. Соединяя таблицу “Остатки” саму с собой можем получить накопительный итог по партиям.

Соединяем таблицы

ВЫБРАТЬ
   *
ИЗ
   ДокТЧ КАК ДокТЧ
   ЛЕВОЕ СОЕДИНЕНИЕ
       Остатки КАК Т1
       ПО ДокТЧ.Товар = Т1.Товар
   ЛЕВОЕ СОЕДИНЕНИЕ
       Остатки КАК Т2
       ПО Т1.Товар = Т2.Товар И Т1.МоментВремени > Т2.МоментВремени

В итоге получаем таблицу.

В таблице из ДокТЧ мы узнаем, сколько списать товаров надо.

В Т1 количество остатка по конкретной партии.

В Т2, после группирования записей будет накопительный итог по партиям.

Выберем только нужные поля:

ВЫБРАТЬ
   ДокТЧ.Товар,
   ДокТЧ.Количество КАК КоличествоДокумента,
   Т1.Партия,
   Т1.КоличествоОстаток КАК КоличествоПартии,
   ISNULL(Т2.КоличествоОстаток,0) КАК НакопительныйИтог
ИЗ
   ДокТЧ КАК ДокТЧ
   ЛЕВОЕ СОЕДИНЕНИЕ
       Остатки КАК Т1
       ПО ДокТЧ.Товар = Т1.Товар
   ЛЕВОЕ СОЕДИНЕНИЕ
       Остатки КАК Т2
       ПО Т1.Товар = Т2.Товар И Т1.МоментВремени > Т2.МоментВремени

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

Для наглядности поместим все во временную таблицу “Данные” и следующим запросом выберем и сгруппируем данные из нее.

Получаем данные о том, сколько списать нужно с конкретной партии

ВЫБРАТЬ
   Товар,
   Партия,
   МАКСИМУМ(КоличествоДокумента) КАК КоличествоДокумента,
   МАКСИМУМ(КоличествоПартии) КАК КоличествоПартии,
   СУММА(НакопительныйИтог) КАК НакопительныйИтог
ИЗ
   Данные КАК Данные
СГРУППИРОВАТЬ ПО Товар, Партия 

 

Данные теперь сгруппированы, товары и партии уникальны.

И опять поместим результат во временную таблицу “Данные2” и очередным запросом рассчитаем сколько необходимо списать с конкретной партии:

ВЫБРАТЬ
   *,
   КоличествоДокумента - НакопительныйИтог КАК ОсталосьСписать
ИЗ
   Данные2 КАК Данные

 

И последняя  итерация: получим в условии сколько нужно списать с конкретной партии (ага, опять с временной таблицей):

ВЫБРАТЬ
   *,
   ВЫБОР КОГДА ОсталосьСписать < КоличествоПартии ТОГДА ОсталосьСписать ИНАЧЕ КоличествоПартии КОНЕЦ КАК Списать
ИЗ
   Данные3 КАК Данные
ГДЕ
   НакопительныйИтог < КоличествоДокумента

Дополнительное условие уберет “лишние” партии, списывать которые не нужно.

Осталось убрать столбцы, которые нам не нужны и получим таблицу для партионного списания.

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

СГРУППИРОВАТЬ ПО
   Товар
ИНДЕКСИРОВАТЬ ПО
   Товар
;


////////////////////////////////////////////////////////////////////////////////

ВЫБРАТЬ
   Товар КАК Товар,
   Партия,
   Партия.МоментВремени КАК МоментВремени,
   КоличествоОстаток,
   СтоимостьОстаток
ПОМЕСТИТЬ Остатки
ИЗ
   РегистрНакопления.ПартииТоваров.Остатки(
           ,
           Товар В
               (ВЫБРАТЬ
                   ДокТЧ.Товар
               ИЗ
                   ДокТЧ КАК ДокТЧ)) КАК ПартииТоваровОстатки

ИНДЕКСИРОВАТЬ ПО
   Товар
;
ВЫБРАТЬ
   *
ИЗ
   ДокТЧ КАК ДокТЧ
   ЛЕВОЕ СОЕДИНЕНИЕ
       Остатки КАК Т1
       ПО ДокТЧ.Товар = Т1.Товар
   ЛЕВОЕ СОЕДИНЕНИЕ
       Остатки КАК Т2
       ПО Т1.Товар = Т2.Товар И Т1.МоментВремени > Т2.МоментВремени
;

ВЫБРАТЬ
   ДокТЧ.Товар,
   ДокТЧ.Количество КАК КоличествоДокумента,
   Т1.Партия,
   Т1.КоличествоОстаток КАК КоличествоПартии,
   ISNULL(Т2.КоличествоОстаток,0) КАК НакопительныйИтог
ПОМЕСТИТЬ Данные
ИЗ
   ДокТЧ КАК ДокТЧ
   ЛЕВОЕ СОЕДИНЕНИЕ
       Остатки КАК Т1
       ПО ДокТЧ.Товар = Т1.Товар
   ЛЕВОЕ СОЕДИНЕНИЕ
       Остатки КАК Т2
       ПО Т1.Товар = Т2.Товар И Т1.МоментВремени > Т2.МоментВремени
;


ВЫБРАТЬ
   Товар,
   Партия,
   МАКСИМУМ(КоличествоДокумента) КАК КоличествоДокумента,
   МАКСИМУМ(КоличествоПартии) КАК КоличествоПартии,
   СУММА(НакопительныйИтог) КАК НакопительныйИтог
ПОМЕСТИТЬ Данные2
ИЗ
   Данные КАК Данные
СГРУППИРОВАТЬ ПО Товар, Партия
;

ВЫБРАТЬ
   *,
   КоличествоДокумента - НакопительныйИтог КАК ОсталосьСписать
ПОМЕСТИТЬ Данные3
ИЗ
   Данные2 КАК Данные
;

ВЫБРАТЬ
   Товар, Партия,
   ВЫБОР КОГДА ОсталосьСписать < КоличествоПартии ТОГДА ОсталосьСписать ИНАЧЕ КоличествоПартии КОНЕЦ КАК Списать

ИЗ
   Данные3 КАК Данные
ГДЕ
   НакопительныйИтог < КоличествоДокумента

 

Вот и все.

В приведенном примере, естественно, мы не сможем продать ложки, их мало, нужно 100, и нож не продадим, его вообще в остатках нет. Но это отдельная история…

Оригинал статьи на моем сайте.

С уважением, Павел Чистов.

партионный учет тэта-запрос

См. также

Инструментарий разработчика Роли и права Запросы СКД Программист Руководитель проекта Платформа 1С v8.3 Управляемые формы Запросы Система компоновки данных Платные (руб)

Инструменты для разработчиков 1С 8.3: Infostart Toolkit. Автоматизация и ускорение разработки на управляемых формах. Легкость работы с 1С.

12000 руб.

02.09.2020    169275    937    403    

905

Запросы Программист Бесплатно (free)

Увидел cheatsheet по SQL и захотелось нарисовать подобное, но про запросы.

18.10.2024    11394    sergey279    18    

65

Запросы Программист Платформа 1С v8.3 Запросы Конфигурации 1cv8 Бесплатно (free)

Столкнулся с интересной ситуацией, которую хотел бы разобрать, ввиду её неочевидности. Речь пойдёт про использование функции запроса АВТОНОМЕРЗАПИСИ() и проблемы, которые могут возникнуть.

11.10.2024    6338    XilDen    36    

83

Запросы Программист Запросы Бесплатно (free)

Отлаживая взаимодействие с базой данных, мы регулярно сталкиваемся с зависающими или подозрительно долго выполняющимися обращениями, негативно влияющими на производительность. О том, как в PostgreSQL выявить подозрительные запросы, основываясь на доступной о них информации, расскажем в статье.

16.08.2024    9068    user1840182    5    

28

Математика и алгоритмы Запросы Программист Платформа 1С v8.3 Запросы Бесплатно (free)

Рассмотрим быстрый алгоритм поиска дублей с использованием hash функции по набору полей шапки и табличных частей.

08.07.2024    2727    ivanov660    9    

22

Запросы СКД Программист Стажер Система компоновки данных Россия Бесплатно (free)

Часто при разработке отчетов в СКД возникает ситуация, когда не совсем понятно, почему отчет выводит не те данные, которые нужны, либо не выводит вовсе. Возникает потребность увидеть конечный запрос, который формирует СКД. Как это сделать, рассмотрим в этой статье.

15.05.2024    10219    implecs_team    6    

48

Запросы Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Часто поступают задачи по произвольному распределению общих сумм. После распределения иногда пропадают копейки. Суть решения добавить АвтоНомерЗаписи() в ВТ распределения, и далее используя функции МАКСИМУМ или МИНИМУМ можем положить разницу копеек в первую или последнюю строку знаменателя распределения.

11.04.2024    3623    andrey_sag    10    

38
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Pervuy 65 20.03.14 13:43 Сейчас в теме
Хорошая статья!
Хотелось бы конечно увидеть контроль остатков, если делать списание таким методом.
2. GROOVY 2511 20.03.14 13:57 Сейчас в теме
(1) Pervuy, контроль остатков можно сделать соединив первые 2 таблицы и получив итоги без учета партий. Там все элементарно.
Или сгруппировав вот этот результат

Чтойта картинки в комменты не вставляются.
agrustny; Pervuy; +2 Ответить
3. Pervuy 65 20.03.14 14:06 Сейчас в теме
4. glek 120 01.04.14 11:17 Сейчас в теме
5. Artem1405 25 05.07.15 20:52 Сейчас в теме
Павел, спасибо за статью! Скажите не планируется ли у вас урок по партионному учету с характеристиками? Не получается их правильно сгруппировать.
6. SmArtist 101 01.02.18 14:22 Сейчас в теме
Вот спасибо, Павел, классный способ с накопительным итогом. Работает правда медленно. Пригодилось для похожей задачи. Переделал на LIFO.
7. melis 97 06.09.20 05:40 Сейчас в теме
Добрый день
Почему при получении таблицы Остатки не использовать внутренние соединение вместо конструкции "В" с вложенным запросом в параметрах таблица?

мне кажется, что так должно быстрее работать - или я в чем-то ошибаюсь?
8. melis 97 06.09.20 05:42 Сейчас в теме
может я что-то упускаю?
9. monster6666 50 29.04.21 10:39 Сейчас в теме
(8) Если вы будете использовать внутреннее соединение, без параметров таблицы, вы сначала получите виртуальную таблицу ВСЕХ партий (что есть афигенно долго в реальных базах), и потом ее соедините с таблицей товаров документа. Сильно сомневаюсь, что так будет быстрее. Именно поэтому, всегда рекомендуется использовать условия в параметрах виртуальных таблиц.
10. melis 97 04.05.21 02:50 Сейчас в теме
Все таблицы в запросах нужно выбирирать всегда с отборами в параметрах только по нужным данным, если есть такая возможность. В ответах для анализа может потребоваться полный набор, но это отчет
11. user642695_crocus.vladikina 20.04.23 19:25 Сейчас в теме
послушайте ну не будет птички по партиям. и что так правильно?
Оставьте свое сообщение