12.
Anton_new01
22.07.24 17:21 Сейчас в теме+0.92 $m
логика:
1. получаем Остаток28 и Остаток67
2. берем целую часть от ТребуетсяХ/67 и сравниваем с остатком67 берем минимум из двух чисел - это количество 67бабин
3 (ТребуетсяХ - количество67бабин * 67)/28 округление вверх и сравниваем с остатком28 - берем минимум из двух чисел это количество 28 бабин
делать эту логику в запросе... ну такое себе.
"ВЫБРАТЬ
| ТоварыНаСкладахОстатки.Товар КАК Товар
| Поместить втОстатокБабина28
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(, , , Товар = &Бабина28) КАК ТоварыНаСкладахОстатки
| ;
|ВЫБРАТЬ
| ТоварыНаСкладахОстатки.Товар КАК Товар
| Поместить втОстатокБабина67
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(, , , Товар = &Бабина67) КАК ТоварыНаСкладахОстатки
| ;
|ВЫБРАТЬ
| Выбор
| Когда ЦЕЛ(&ТребуетсяХ/67) > втОстатокБабина67.Товар Тогда втОстатокБабина67.Товар
| Иначе ЦЕЛ(&ТребуетсяХ/67)
| Конец Как Количество67бабин
| Поместить втКоличество67бабин
|ИЗ
| втОстатокБабина67 КАК втОстатокБабина67
| ;
|ВЫБРАТЬ
| Выбор
| Когда ЦЕЛ((&ТребуетсяХ - втКоличество67бабин.Количество67бабин*67)/28)+1 > втОстатокБабина28.Товар Тогда втОстатокБабина28.Товар
| Иначе ЦЕЛ((&ТребуетсяХ - втКоличество67бабин.Количество67бабин*67)/28)+1
| Конец Как Количество28бабин
| Поместить втКоличество28бабин
|ИЗ
| втКоличество67бабин как втКоличество67бабин,
| втОстатокБабина28 КАК втОстатокБабина28,
| ;
|ВЫБРАТЬ
| втКоличество67бабин.втКоличество67бабин,
| втКоличество28бабин.втКоличество28бабин
|ИЗ
| втКоличество67бабин как втКоличество67бабин,
| втКоличество28бабин КАК втКоличество28бабин"
Показать
PS. небольшая не точность в Количество28бабин - так как нет функции окрулить вверх я использовал взять цел и +1 - это не всегда равно окрулению вверх, если у нас число кратно 28.
(9)
1. Делаем запрос на остатки
2. Устанавливаем параметр - НеобходимоеКоличество
3. Логика:
СколькоНужно28 = НеобходимоеКоличество / 28;
СколькоНужно67 = НеобходимоеКоличество / 67;
Если (СколькоНужно67 < 1) И (СколькоНужно28 < 1) Тогда
Ответ = Количество28 * 1;
Иначе Если (СколькоНужно67 < 1) И (СколькоНужно28 > 1) Тогда
Ответ = Количество67 * 1;
И методами сравнения далее определяем, честно сказать, не знаю как в запросе можно обрабатывать числа т.к. в основном нам будут интересны числа после запятой.
может быть перебор всех вариантов бобин с расчетом остатка
и выбор варианта с минимальным остатком
готовим две таблицы с бобинами 1 и 2, помещаем во времТаб
бобина, Количество (при формировании этих таблиц как раз и ограничиваем их остатками)
б1, 0
б1, 1
б1, 2
б1, 3
б1, 4 и тд
и
б2, 0
б2, 1
б2, 2
б2, 3
б2, 4 и тд
соединяем эти две таблицы через запятую, получаем всевозможные варианты сочетаний бодин
и рассчитываем общую длину в каждой строке
затем отбираем строчки где общая длинна чуть больше требуемой,
(так как операции умножения и сложения самые простые, результат будет почти мгновенный)
12.
Anton_new01
22.07.24 17:21 Сейчас в теме+0.92 $m
логика:
1. получаем Остаток28 и Остаток67
2. берем целую часть от ТребуетсяХ/67 и сравниваем с остатком67 берем минимум из двух чисел - это количество 67бабин
3 (ТребуетсяХ - количество67бабин * 67)/28 округление вверх и сравниваем с остатком28 - берем минимум из двух чисел это количество 28 бабин
делать эту логику в запросе... ну такое себе.
"ВЫБРАТЬ
| ТоварыНаСкладахОстатки.Товар КАК Товар
| Поместить втОстатокБабина28
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(, , , Товар = &Бабина28) КАК ТоварыНаСкладахОстатки
| ;
|ВЫБРАТЬ
| ТоварыНаСкладахОстатки.Товар КАК Товар
| Поместить втОстатокБабина67
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(, , , Товар = &Бабина67) КАК ТоварыНаСкладахОстатки
| ;
|ВЫБРАТЬ
| Выбор
| Когда ЦЕЛ(&ТребуетсяХ/67) > втОстатокБабина67.Товар Тогда втОстатокБабина67.Товар
| Иначе ЦЕЛ(&ТребуетсяХ/67)
| Конец Как Количество67бабин
| Поместить втКоличество67бабин
|ИЗ
| втОстатокБабина67 КАК втОстатокБабина67
| ;
|ВЫБРАТЬ
| Выбор
| Когда ЦЕЛ((&ТребуетсяХ - втКоличество67бабин.Количество67бабин*67)/28)+1 > втОстатокБабина28.Товар Тогда втОстатокБабина28.Товар
| Иначе ЦЕЛ((&ТребуетсяХ - втКоличество67бабин.Количество67бабин*67)/28)+1
| Конец Как Количество28бабин
| Поместить втКоличество28бабин
|ИЗ
| втКоличество67бабин как втКоличество67бабин,
| втОстатокБабина28 КАК втОстатокБабина28,
| ;
|ВЫБРАТЬ
| втКоличество67бабин.втКоличество67бабин,
| втКоличество28бабин.втКоличество28бабин
|ИЗ
| втКоличество67бабин как втКоличество67бабин,
| втКоличество28бабин КАК втКоличество28бабин"
Показать
PS. небольшая не точность в Количество28бабин - так как нет функции окрулить вверх я использовал взять цел и +1 - это не всегда равно окрулению вверх, если у нас число кратно 28.
(25) т.е. критерий правильно/ не правильно - это минимум выражения количество67*67+количество28*28 ?
сейчас подумаю какой алгоритм составить, для такого результата.
(25)
алгоритм:
1. подготавливаем таблицу нумерации от 0 до 99.
2. считаем все возможные варианты количества 67 бабин
от 0 до максимум Кол67 = Мин( ЦЕЛ(&НеобходимоеКоличество / 67) + 1, Остаток67)
3. к каждому варианту количества 67 бабин считаем количество 28 бабин по формуле
Кол28=Мин(ОкруглВверх((ТребуетсяХ - Кол67)/28), Остаток28)
4. находим минимум кол67*67+кол28*28
PS. ограничение метода в количестве предварительной таблицы в 67*100=6700 метров т.к. у нас сотня вариантов заложена нумератором. Можно заложить больше, но в любом случае будет некое ограничение.
ВЫБРАТЬ
0 КАК Номер
ПОМЕСТИТЬ втПятерка
ОБЪЕДИНИТЬ
ВЫБРАТЬ
1
ОБЪЕДИНИТЬ
ВЫБРАТЬ
2
ОБЪЕДИНИТЬ
ВЫБРАТЬ
3
ОБЪЕДИНИТЬ
ВЫБРАТЬ
4
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
АВТОНОМЕРЗАПИСИ() КАК Номер,
Пятерка1.Номер КАК НомерП
ПОМЕСТИТЬ втСотня
ИЗ
втПятерка КАК Пятерка1,
втПятерка КАК Пятерка2,
втПятерка КАК Пятерка3
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ТЗ.Количество28 КАК Кол28,
ТЗ.Количество67 КАК Кол67
ПОМЕСТИТЬ втОстатки
ИЗ
&ТЗ КАК ТЗ
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВЫБОР
КОГДА ЦЕЛ(&НеобходимоеКоличество / 67) + 1 >= втОстатки.Кол67
ТОГДА втОстатки.Кол67
ИНАЧЕ ЦЕЛ(&НеобходимоеКоличество / 67) + 1
КОНЕЦ КАК МаксКол67
ПОМЕСТИТЬ втОстатки67
ИЗ
втОстатки КАК втОстатки
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
втСотня.Номер - 1 КАК Кол67,
ВЫБОР
КОГДА (&НеобходимоеКоличество - (втСотня.Номер + 1) * 67) / 28 > Остатки.Кол28
ТОГДА Остатки.Кол28
ИНАЧЕ (ВЫРАЗИТЬ((&НеобходимоеКоличество - (втСотня.Номер + 1) * 67) / 28 - 0.5 КАК ЧИСЛО(15, 0))) + 1
КОНЕЦ КАК Кол28
ПОМЕСТИТЬ втВсеВариантыБабин
ИЗ
втСотня КАК втСотня,
втОстатки67 КАК втОстатки67,
втОстатки КАК Остатки
ГДЕ
втСотня.Номер - 1 >= втОстатки67.МаксКол67
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ ПЕРВЫЕ 5
ВсеВариантыБабин.Кол67 КАК Кол67,
ВсеВариантыБабин.Кол28 КАК Кол28,
ВсеВариантыБабин.Кол67 * 67 + ВсеВариантыБабин.Кол28 * 28 КАК Сортировка
ИЗ
втВсеВариантыБабин КАК ВсеВариантыБабин
внесу свой гов.. запрос, 35 и 280 это значение в метрах, которое будет передаваться в качестве параметра. Не продумал до конца логику, вдруг немного поможет)
ВЫБРАТЬ
ВЫБОР
КОГДА 35 > 28
ТОГДА
ВЫБОР КОГДА ЦЕЛ(35 / 28) = 35 ТОГДА ЦЕЛ(35 / 28)
КОГДА ЦЕЛ(35 / 28) > 28ТОГДА ЦЕЛ(35 / 28) + 1
ИНАЧЕ 0
КОНЕЦ
КОГДА 35 = 28
ТОГДА
1
ИНАЧЕ
0
КОНЕЦ КАК Количество28
,ВЫБОР
КОГДА 280 >= 67
ТОГДА
ЦЕЛ(280 / 67)
ИНАЧЕ
0
КОНЕЦ КАК Количество67
ВЫБРАТЬ
ТЗ.Количество28 КАК Количество28,
ТЗ.Количество67 КАК Количество67
ПОМЕСТИТЬ ОстаткиНаСкладе
ИЗ
&ТЗ КАК ТЗ
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВЫБОР
КОГДА ЦЕЛ(&НеобходимоеКоличество / 67) > ОстаткиНаСкладе.Количество67
ТОГДА ОстаткиНаСкладе.Количество67
ИНАЧЕ ЦЕЛ(&НеобходимоеКоличество / 67)
КОНЕЦ КАК Количество67,
ВЫБОР
КОГДА (&НеобходимоеКоличество - ЦЕЛ(&НеобходимоеКоличество / 67) * 67) / 28 > ОстаткиНаСкладе.Количество28
ТОГДА ОстаткиНаСкладе.Количество28
ИНАЧЕ (ВЫРАЗИТЬ((&НеобходимоеКоличество - ЦЕЛ(&НеобходимоеКоличество / 67) * 67) / 28 - 0.5 КАК ЧИСЛО(15, 0))) + 1
КОНЕЦ КАК Количество28
ИЗ
ОстаткиНаСкладе КАК ОстаткиНаСкладе
//таб с номерами > мак остатка (для примера взято 10)
Выбрать 0 как Номер поместить втНомера
объединить все Выбрать 1
объединить все Выбрать 2
объединить все Выбрать 3
объединить все Выбрать 4
объединить все Выбрать 5
объединить все Выбрать 6
объединить все Выбрать 7
объединить все Выбрать 8
объединить все Выбрать 9
объединить все Выбрать 10
;
//эмуляция запроса остатков по бобинам
Выбрать "Б28" как товар, 9 как Количество поместить втОстатки
объединить все Выбрать "Б67", 8
;
//две таблицы с товарами для расчета
Выбрать
втОстатки.Товар,
втНомера.Номер как Количество,
28 как длина
поместить втТаб1
из
втОстатки
левое соединение втНомера
по втОстатки.Количество >= втНомера.Номер
где
втОстатки.Товар = "Б28"
;
Выбрать
втОстатки.Товар,
втНомера.Номер как Количество,
67 как длина
поместить втТаб2
из
втОстатки
левое соединение втНомера
по втОстатки.Количество >= втНомера.Номер
где
втОстатки.Товар = "Б67"
;
Выбрать первые 1 //3
т1.Товар,
т1.Количество,
т2.Товар,
т2.Количество,
т1.Количество * т1.Длина + т2.Количество * т2.Длина как Длина
из
втТаб1 т1, втТаб2 т2
где
т1.Количество * т1.Длина + т2.Количество * т2.Длина >= &НужнаяДлина
Упорядочить по
5
(1) Скучно....
Усложнил задачу из спортивного интереса.
Бобины могут быть любой длины, а не только 67 и 28. У каждой бобины есть место хранения и дата производства.
Необходимо подобрать либо заданное количество метража, а если подобрать не удаётся то ближайшее большее. При этом необходимо стараться подбирать бобины с максимальной длиной в первую очередь и среди прочих равных брать с более ранней датой производства. Если среди двух одинаковых бобин дата производства одинаковая, то первую попавшуюся. Не важно какую из этих двух.
Если метража на складе не достаточно, то в результате должны быть все имеющиеся.
Результат: метраж бобины через запятую, места хранения через запятую, общий метраж (sum_kol).
Для понимания алгоритма вывел ещё и служебную не обязательную колонку (sum_npp).
Запрос на PsgSQL. В начале задается количество в
vt_const as (SELECT 1000 as a)
Вместо 1000 можно рисовать любые положительные циферки. Это тот метраж, который запросил клиент.
Проверял кто результат в запросе {26}?
Для 129 и 132 будут результаты 129 и 133 (на скринах).
Такой же по сути запрос отработал и на SQLite и на MS SQL.
Только в 1С, к огромному сожалению, нет рекурсивных запросов и обычной функции нумерации (только подобие, реализованное странным образом).