Имя: Пароль:
1C
 
Выбор наибольшей цены товара из табличной части
,
0 НоваяВолна
 
11.05.21
13:53
Есть документ, Приобретение Товаров в котором могут быть сроки с одинаковой номенклатурой, но разной ценой. При проведении этого документа автоматически должен создаваться документ Установка цен номенклатуры.
    При этом понятно что в регистр цены номенклатуры не может записываться одинаковая номенклатура с тем же регистратором.
Если есть дублирование номенклатуры, то надо отобрать позицию с большей ценой и только ее переносить в документ "Установка цен номенклатуры", остальные пропускать.
Подскажите каким образом проще всего выбрать максимальную цену дублирующийся номенклатуры в табличной части ещё не записанного документа?
1 Aleksey
 
11.05.21
13:54
запросом?
2 Ненавижу 1С
 
гуру
11.05.21
13:55
При проведении документ уже записан
3 Гений 1С
 
гуру
11.05.21
14:31
(1) (2) поддерживаю (двачую) ораторов. ;-)
документ записан, запросом.
4 Малыш Джон
 
11.05.21
15:06
(0)>>Подскажите каким образом проще всего выбрать максимальную цену дублирующийся номенклатуры в табличной части ещё не записанного документа?

Давай, накидай нам какие варианты рассматриваешь, а мы скажем какой проще)
5 benj
 
11.05.21
15:43
Типо так
    ТаблицаДанных = ДокументПриобретения.Товары.Выгрузить(,"Номенклатура,Цена");
    Запрос = Новый Запрос;
    Запрос.Текст =
        "ВЫБРАТЬ
        |    Товары.Номенклатура КАК Номенклатура,
        |    Товары.Цена КАК Цена
        |ПОМЕСТИТЬ Данные
        |ИЗ
        |    &Товары КАК Товары
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////
        |ВЫБРАТЬ
        |    Данные.Номенклатура КАК Номенклатура,
        |    МАКСИМУМ(Данные.Цена) КАК Цена
        |ИЗ
        |    Данные КАК Данные
        |
        |СГРУППИРОВАТЬ ПО
        |    Данные.Номенклатура";
    
    Запрос.УстановитьПараметр("Таблица",ТаблицаДанных)
    РезультатЗапроса = Запрос.Выполнить();
    
    ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
    
    Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
        // Вставить обработку выборки ВыборкаДетальныеЗаписи
    КонецЦикла;
6 benj
 
11.05.21
15:44
(5) Ссори ошибку сделал в параметре

    ТаблицаДанных = ДокументПриобретения.Товары.Выгрузить(,"Номенклатура,Цена");
    Запрос = Новый Запрос;
    Запрос.Текст =
        "ВЫБРАТЬ
        |    Товары.Номенклатура КАК Номенклатура,
        |    Товары.Цена КАК Цена
        |ПОМЕСТИТЬ Данные
        |ИЗ
        |    &Товары КАК Товары
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////
        |ВЫБРАТЬ
        |    Данные.Номенклатура КАК Номенклатура,
        |    МАКСИМУМ(Данные.Цена) КАК Цена
        |ИЗ
        |    Данные КАК Данные
        |
        |СГРУППИРОВАТЬ ПО
        |    Данные.Номенклатура";
    
    Запрос.УстановитьПараметр("Товары",ТаблицаДанных)
    РезультатЗапроса = Запрос.Выполнить();
    
    ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
    
    Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
        // Вставить обработку выборки ВыборкаДетальныеЗаписи
    КонецЦикла;
7 lubitelxml
 
11.05.21
15:49
(6) а где же РАЗЛИЧНЫЕ?
8 benj
 
11.05.21
15:51
(7) А смысл есть в группировке по номенклатуре и цене выбирать различные?
9 НоваяВолна
 
12.05.21
07:36
(6) сделал вот так

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

                
                Запрос.УстановитьПараметр("Товары",ТаблицаДанных);
                Запрос.УстановитьПараметр("Ссылка",ТекущийОбъект.Ссылка);
                РезультатЗапроса = Запрос.Выполнить();
            
                ТЗТовары = РезультатЗапроса.Выгрузить();



В результате в ТЗТовары имеется две строки с одинаковой номенклатурой, в поле цена у каждой указана максимальная для этой номенклатуры цена в документе
10 Ненавижу 1С
 
гуру
12.05.21
07:53
(9) зачем ты тащишь суммы и количество? Естественно они разные для разных строк могут быть. Тебе нужно только номенклатура и цена.

И при проведении документ уже записан. Тогда не нужно загружать таблицу параметром, делать временную таблицу и левое соединение
11 Simod
 
12.05.21
08:00
(6), (9) Зачем такие сложности?

МаксЦенаНоменклатуры = Новый Соответствие;
Для Каждого СтрокаТЧ Из ЭтотОбъект.Товары Цикл
    ЦенаНоменклатуры = МаксЦенаНоменклатуры.Получить(СтрокаТЧ.Номенклатура);
    Если ЦенаНоменклатуры = Неопределено
        ИЛИ СтрокаТЧ.Цена > ЦенаНоменклатуры Тогда
        МаксЦенаНоменклатуры.Вставить(СтрокаТЧ.Номенклатура, СтрокаТЧ.Цена);
    КонецЕсли;
КонецЦикла;
12 Sserj
 
12.05.21
08:05
А все уверены что Запрос при проведении лучший вариант?
Зачем напрягать БД, грузить в нее временную таблицу или вон еще лучше выполнять полноценный запрос по документам если все нужные данные уже загружены в память.
Неужто банальный обход каждой строки в памяти будет дольше запроса.
Что типа
максЦены = Новый Соответствие()
Для Каждого Строка из ТабличнаЧасть Цикл
  последняяЦена = Строка.Получить(Строка.Номенклатура);
  Если (последняяЦена = Неопределено) или (последняяЦена < Строка.Цена) Тогда
    максЦены.Вставить(Строка.Номенклатура, последняяЦена);
  КонецЕсли;
КонецЦикла;
Ну а потом обход и запись.
13 Ненавижу 1С
 
гуру
12.05.21
08:06
(11) а потом ещё один цикл чтобы соответствие в ТЧ превратить. Даешь больше кодинга с циклами
14 Sserj
 
12.05.21
08:11
(13) Т.е. "даешь меньше кодинга" оправдываешь лишнии запросы в обработке проведения, удорожания транзакций в времени блокировок данных?
15 НоваяВолна
 
12.05.21
08:12
(10) в общем разобрался. Убрал из второй таблицы количество и сумму, сделал ее временной и окончательным запросом прилепил количество и сумму.
Всем спасибо!
16 Ненавижу 1С
 
гуру
12.05.21
08:21
(14) неоправданная оптимизация в ущерб читаемости кода

Но вопрос на поболтать чисто. Однозначного мнения нет
17 Bigbro
 
12.05.21
08:26
поддержку (11) (14)
все что можно делать не дергая базу - надо делать именно так.
18 Sserj
 
12.05.21
08:31
(16) А почему бы и не поболтать, зачем еще форум то нужен :)
"..в ущерб читаемости кода.." - по мне так красота текста запроса очень спорная, если следовать религии ЧистогоКода то маленькие функции будут выглядеть гораздо симпотичнее портянок запроса:
Фунцкия получитьСтруктуруМаксимальныхЦен()
  .....
  Возврат максимальныеЦены;
КонецФункции

Функция УстановкаМаксимальныхЦен(максимальныеЦены)
  документУстановкиЦен = Неопределено;
  ...
  Возврат документУстановкиЦен
КонецФункции

Процедура ОбработкаПроведения()
...
максимальныеЦены = получитьСтруктуруМаксимальныхЦен();
Если УстановкаМаксимальныхЦен(максимальныеЦены) = Неопределено Тогда
  Отказ = Истина;
КонецЕсли
КонецПроцедуры

2. "..неоправданная оптимизация в ущерб читаемости кода.." - та ладно, если документ на тысячи строк это будет ой какая "оправданность".
19 fisher
 
12.05.21
09:08
(0) Ну, я бы тупо создал соответствие номенклатура/цена и за один проход заполнил его номенклатурой с максимальными ценами (т.е. сначала пробуем получить цену номенклатуры из соответствия и если еще нет или меньше чем текущая - пишем новые данные).
20 fisher
 
12.05.21
09:10
Я слоупок. В (11) уже реализация.
(16) "Неоправданная оптимизация"? Надеюсь, это был сарказм. Это прямой как железная дорога лобовой подход.
21 ChMikle
 
12.05.21
09:12
сортировать ТЗ по цене по возрастанию и записывать. Не прокатит так  ?
22 fisher
 
12.05.21
09:12
Хотя да, постановка задачи неправильная. Документ будет уже записан.
23 mikecool
 
12.05.21
09:16
если все данные уже есть - зачем еще запрос?
24 fisher
 
12.05.21
09:20
(23) При проведении так или иначе будут какие-то запросы. Впендюрить в пакет подготовку данных еще и для этой задачи будет вполне оптимальным вариантом. В общем, вопрос вкусовой и ситуативный.
25 BIP1
 
12.05.21
09:56
(9) Скажите, чем вы руководствовались, когда эту задачу решили с помощью такой "портянки" кода с запросом? Чем вас не устроил цикл?
Запрос "моднее", чем цикл или что?
Смысл запроса ускользает конкретно в данном случае. Что не так с ЭтотОбъект.Товары (или как там у вас в документе ТЧ называется)? (16) Сравните "портянку" автора и один из вариантов с циклом. Использование запроса явно "в ущерб читаемости кода". Любят иногда люди пихать циклы везде, где только можно:) Зато ЗАПРОС! Авторитета так программистского добирают или чего? непонятно🤷‍♂️
26 Ненавижу 1С
 
гуру
12.05.21
10:06
(25) затем что вы привели только половину
потом еще это соответствие в ТЧ надо развернуть

В 1С нет функциональщины типа LINQ и поэтому все это выглядит крайне некрасиво
27 BIP1
 
12.05.21
10:09
(26) Так "вторая половина" и с запросом будет. Её можно в отдельную процедуру/функцию оформить и передать туда данные Товар+Цена.
28 Bigbro
 
12.05.21
10:13
(26) что некрасивого в простейшем цикле по ТЧ который строит структуру-соответствие?
смысл этого поймет любой новичок с первого взгляда.
более того и с точки зрения работы с БД данный подход более правильный - не нужно дергать базу когда без этого можно обойтись.
вам кажется это мелочи тут дернул легкий запросик там.
а в итоге из этих тут и там может вырасти паразитный фоновый режим нагрузки, который составит существенную долю и уже будет оказывать влияние на работу.
зачем??
я бы понял, если пришлось бы писать некий архисложный трехэтажный алгоритм из костылей а реализация запросом была бы в 3 строки.
но тут не тот случай.
29 BIP1
 
12.05.21
10:23
(28) К тому же, прямо в этом цикле можно заполнять и документ УстановкаЦенНоменклатуры. А используя ЗаполнитьЗначенияСвойств() количество строк кода можно свести к минимуму. А любые "некрасивости" можно сопроводить веским комментарием😀
Но кто-то любит запросы и всё тут🤷‍♂️ несмотря на то, что такие "портянки" иногда фиг поймешь с первого/второго раза
30 НоваяВолна
 
12.05.21
10:25
(25) В (1), (3), (6) посоветовали запросом. Запросом и сделал. И по моему запрос читается проще, чем два цикла подряд.
31 Bigbro
 
12.05.21
10:27
(30) ну против авторитета (3) конечно идти не стоит.
умолк.
32 Sserj
 
12.05.21
10:49
(30) Так не делай два цикла подряд :)
Почитай старину Мартина и спрячь все в маленький функциях.
Циклы есть всегда и везде, по сути в язаках программирования ничего и нет кроме переменных, условий и циклов (ну если быть точнее то и циклов то нет, это всего лишь прикрытие для ненавистного GOTO).
Вопрос только на каком уровне абстракции они спрятаны.
33 fisher
 
12.05.21
10:57
(32) Тут когда народ заглядывает в БСП и видит подход старины Мартина - пеной исходят. Мол стек вызовов за страницу вылазит, а можно было бы все в одной.
Я не хочу быть самым богатым человеком на кладбище. Засыпать с чувством, что за день я сделал какую-нибудь потрясающую вещь — вот что меня интересует. Стив Джобс