Имя: Пароль:
1C
1С v8
Списание партий по FIFO одним запросом
0 experimentator76
 
02.02.12
20:12
Вот запрос.
Смысл - одним запросом рассчитать количество к списанию в разрезе партий по множеству номенклатуры.
На выходе только товары, по которым достаточно партий.
Просьба проверить - все ли корректно работает.


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

СГРУППИРОВАТЬ ПО
              РасходТовары.Номенклатура
;

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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
              ТоварыВсе.Номенклатура,
              ТоварыВсе.Количество
ПОМЕСТИТЬ Товары
ИЗ
              ТоварыВсе КАК ТоварыВсе
                             ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
                                           Партии.Номенклатура КАК Номенклатура,
                                           СУММА(Партии.Остаток) КАК ОстатокОбщий
                             ИЗ
                                           Партии КАК Партии
                             
                             СГРУППИРОВАТЬ ПО
                                           Партии.Номенклатура) КАК П
                             ПО (П.Номенклатура = ТоварыВсе.Номенклатура)
                                           И (П.ОстатокОбщий >= ТоварыВсе.Количество)
;

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

СГРУППИРОВАТЬ ПО
              Товары.Номенклатура,
              ВТ1.Партия,
              ВТ1.МоментВремени,
              ВТ1.Остаток,
              Товары.Количество

ИМЕЮЩИЕ
              Товары.Количество > СУММА(ВТ2.Остаток) - ВТ1.Остаток

УПОРЯДОЧИТЬ ПО
              ВТ1.МоментВремени
1 palpetrovich
 
02.02.12
21:09
хм, дежавю
пару за сегодня раз видел подобную тему ...или это резюме?
2 experimentator76
 
02.02.12
21:22
сегодня только зарегился - не судите строго за косяки с движком
я слышал давно что одним запросом сие нереализуемо
набросал - работает - есть подозрение что где-то может быть косяк,
так как "программ без багов не бывает"
если косяка нет - буду применять тогда
3 GROOVY
 
02.02.12
21:27
Вполне реализуемо, только при большом количестве парти (обычное дело) такой запрос буде дико тормозить при соединениях.
4 GROOVY
 
02.02.12
21:28
Зачем хотите именно в запросе рассчитать партии списания? Не проще ли это делать уже в модуле. И писать проще, и для системы легче.
5 Пират
 
02.02.12
21:29
(0) я бы разделил в таком случае количественный и суммовой учет по партиям на два регистра
6 Поpyчик-4
 
02.02.12
21:31
(0) Лисапед. Штатные механизмы ужо не канают, нам бы тоже самое, но с квадратно-перламутровыми?
7 experimentator76
 
02.02.12
21:52
не скрою что был еще спортивный интерес :)
8 experimentator76
 
02.02.12
21:59
(3) не факт - надо проверять
(4) теоретически запросом должно быть быстрее - для модуля остается проверка и сигнализация частью пакетного запроса о несписанных товарах + отказ а результат запроса можно без дополнительных расчетов записывать в регистр

(5) суммового собственно в запросе не предусмотрено, но если он корректно в принципе работает то можно прикрутить

(6) в смысле - те что в типовых конфигурациях ? прям вот так выпилить из типовой и применять в своей ?
9 experimentator76
 
02.02.12
22:01
(4) а партии чтоб не залеживались надо быстро пускать в расход :)
10 Reaper_1c
 
02.02.12
22:08
(8) Проверено. Факт. Железобетонный. Медленнее минимум в 1.5-2 раза. Транзакция растягивается, конфликты блокировок множатся. Автора лишают премии.
11 Азазелло
 
02.02.12
22:15
(10) Нет, ну в свое время @Ненавижу1С проявлял теоретический интерес к возможности решения СЛАУ запросами. Здесь, можно сказать, тот же случай :)
12 experimentator76
 
02.02.12
22:16
(10) верю :)))
13 experimentator76
 
02.02.12
22:18
(11) ну не всеж только рутина в обмен на премии :) хочется эдакий изврат забацать

тормоза проверю на выхах - надо выбрать базу для насилия
14 Азазелло
 
02.02.12
22:19
(13) Завтра проверим ;)
15 experimentator76
 
02.02.12
22:21
кстати соединения производятся временной таблицей на саму себя
может и не будет падения производительности

(14) завтра нельзя - нащальника строгая :))) ;)
16 Reaper_1c
 
02.02.12
22:22
(11) Так и 1Сники проявляли. Не взлетело.
17 experimentator76
 
02.02.12
22:23
(16) это кто такие ? разработчики платформы?
18 МуМу
 
02.02.12
22:50
Доказано теоритически что партионка расчитывается на SQL только курсорами а стало быть смысла писать одним запросом нет.(проще на клиенте в цикле) Конечно может чего нибудь в 1С на сервер приложений намудрили с кешированием но это врядли.
19 Reaper_1c
 
02.02.12
22:54
(18) Ничего не мутили. Я по глупости когда 8-ку осваивал проверял. Списание силами сервера приложений делает супермегазапрос как стоячего.
20 experimentator76
 
02.02.12
23:12
(18) наверное мой уровень не позволяет мне понять что Вы написали

(19) поясните - как чего стоячего?
как выяснили что делает супермегазапрос ?
21 experimentator76
 
02.02.12
23:13
наверное не в теории смогу проверить только сам что там в результате будет мегастоять
22 Пират
 
02.02.12
23:21
(18) если приложение управляемое, то лучше все-таки запросом, имхо
23 experimentator76
 
02.02.12
23:25
(22) только 8.2, только на сервере и только запросом
аминь :)
24 Новиков
 
02.02.12
23:33
(23) не знаю сколько тебе лет, сколько ты чего видел в жизни, но открой типовые и посмотри там реализацию фифо. И да - там не дебилы написали списание именно кодом, а не запросом.
25 experimentator76
 
02.02.12
23:39
(24) в типовых ошибки находил - бывало
но суть не в том - знаю я или не знаю типовой подход
суть в (0)
26 experimentator76
 
02.02.12
23:39
год рождения указан в нике
27 Reaper_1c
 
03.02.12
09:41
(21) Это ты сейчас кого теоретиком обозвал? Если ты не знаешь в какую позу поставишьь СУБД соединением таблиц по условию типа ">=" по дате - флаг тебе в руки, барабан на шею...
28 Ненавижу 1С
 
гуру
03.02.12
09:42
29 experimentator76
 
03.02.12
21:25
(27) не хотел никоим образом оскорбить
но наверное согласитесь что один практик стоит трех теоретиков

(28) похожий алгоритм - я его видел однажды и его часть с соединениями использовал для расчета накопительных итогов
спасибо за идею, которая подтолкнула меня ее развить дальше
и реализовать запрос (0) чтобы избежать переборов и вычислений кодом вне запроса (так называемый и почитаемый в народе "типовой подход")

как обещал на выхах потестю эти соединения на вшивость
возможно вы ребята и правы и теория это сила :))
30 Immortal
 
03.02.12
22:15
(10)в простых случаях запрос быстрее
31 experimentator76
 
03.02.12
22:20
(30) подскажите пример сложного случая - я его воссоздам
32 Злопчинский
 
04.02.12
03:57
на Исе поищите - обсуждались эти вопросы вроде активно... или я туплю - может и здесь было...
33 Эмбеддер
 
04.02.12
07:30
(0) Тут целых 4 запроса вместо 1
34 experimentator76
 
04.02.12
10:05
(33) верно подмечено! два первых непосредственно к данным, один контрольный и один расчетный\результирующий
НО пакетный один и выполняться должен быстрее чем 4 отдельных последовательных запроса

(32) туплю - иса это где ?
35 Эмбеддер
 
04.02.12
10:22
(34) я на 7-ке когда выбирал данные прямыми запросами, использовал курсоры, чтобы код выполнялся не в 1С, а на сервере. хотя была альтернатива или все на 1С или запросами
36 experimentator76
 
04.02.12
10:39
(35) скуль это другая песня :) с прямыми запросами в семерке работал, но непосредственно в самом скуле мало писал
я слышал что там можно организовать рекурсивность запроса - а это новые возможности для закура

сейчас работаю с 8.2 и интересно ее мощами реализовать, не выходя за рамки ограниченности ее платформы
37 Эмбеддер
 
04.02.12
10:50
(36) Рекурсивный запрос хотел использовать для иерархии номенклатуры в 7-ке. Просто иерархию можно было получить, но в реальном запросе с итогами применить не удалось из-за ограничений
38 experimentator76
 
04.02.12
10:56
(37) я видел как на скуле решается задача получения иерархии справочника
сейчас есть неявное желание оставаться в рамках платформы 8.2
но отсутствие рекурсивности в запросах восьмерки тормозит реализацию целого ряда задач
к примеру (0) можно было бы реализовать возможно проще и без соединений
а также решить задачу умножения между строками
39 БалбесВ1с
 
04.02.12
11:04
(34)Иса - инф0старт
40 experimentator76
 
04.02.12
11:07
(39) спасибо - почитаю по этой теме
41 Эмбеддер
 
04.02.12
11:09
(38) Тут остается или поверить мне на слово что на практике рекурсивный запрос бесполезен с существующими ограничениями или попробовать самому
а по поводу списания в запросе мое мнение что скорости не добавит, если не наоборот
42 experimentator76
 
04.02.12
11:18
(41) буду готовить базу - проверю скорость типовым подходом и пакетным запросом
43 experimentator76
 
04.02.12
11:26
Вот нашел на ИСЕ нечто похожее
http://forum.infostart.ru/forum24/topic41395/message462692/#message462692
44 Immortal
 
06.02.12
21:09
(31)списание партий в типовой - это сложный случай
45 Immortal
 
06.02.12
21:10
и, наверное, (18) прав.
46 кащщей
 
06.02.12
21:22
Надо бы на NuLL проверить еще...вроде бы не забыть.
47 hhhh
 
06.02.12
21:29
а разве моменты времени сравниваются на >= ? Что-то я пропустил.
48 experimentator76
 
06.02.12
21:59
тестовая база создана случайным образом

2000 уникальных товаров
30000 партий\приходов
3500 расходов - больше создать терпения не хватило
число строк товаров 1..50

проведение таким запросом не вешает базу
поправлю позже алгоритм подбора партий чтобы списывалось все количество сразу а не частями как сейчас
так как это долго происходит при таком количестве партий

впереди тестирование общепринятого алгоритма списания и одним запросом
49 experimentator76
 
06.02.12
22:04
(44) плата за универсальность этого механизма
(45) мне показалось что это семерочный подход или я не понял высказывание
(46) товары соединяются с партиями внутренне и товары только те на которые есть остатки в принципе
проверку на недостаток партий допишу - это + запрос в пакет
(47) еще как сравниваются!
50 experimentator76
 
06.02.12
22:14
да и платформа 8.2 - база SQL
51 кащщей
 
06.02.12
22:24
(49), При соединениях, тем более внутренних принято проверять значения полей на значение NULL, Иначе такие выражения в запросе как  
СУММА(ВТ2.Остаток) - ВТ1.Остаток КАК ПредыдущийОстаток,
дадут совершенно непредсказуемый результат, точнее не дадут вооще. даже если есть Вт2.остаток
52 Азазелло
 
06.02.12
23:51
(51) o_O NULL никак не может получиться при _внутреннем_ соединение...
Компьютер — устройство, разработанное для ускорения и автоматизации человеческих ошибок.