Добрый день! Вот попалась задачка, и честно говоря, в начале показалась ничего особенного, но попытавшись решить, начал спотыкаться, появились сомнения.
Решил сюда выкинуть, может у кого -то появятся мыслишки по решению. Условие пишу как есть:
Необходимо реализовать универсальную функцию вида: СкорректироватьЗаписи(ИмяРегистра, ИсходныеДвижения, ЦелевыеДвижения).
Где ИмяРегистра - имя регистра накопления (строка);
ИсходныеДвижения - набор исходных движений (тип - Таблица значений)
ЦелевыеДвижения - набор целевых движений (тип - Таблица значений)
Функция должна возвращать набор записей соответствующего регистра (в виде таблицы значений), при записи котрого (в рамках данной задачи запись реализовывать не надо) в системе будут целевые движения. Исходные движения при этом не удаляются.
Например, существует движения регистра "Остатки номенклатуры", Исходные движения (Приходная №2):
Номенк Колво Сум
Kohinor 60 390
Паркер 40 3800
И есть движения регистра "Остатки номенклатуры", Целевые движения (Приходная №1):
Номенк Колво Сум
Kohinor 10 70
Паркер 10 1000
На выходе функция должна вернуть таблицу значений следующего вида:
Номенк Колво Сум
Kohinor -50 -320
Паркер -30 -2800
Функция должна быть универсальной, т.е. на вход могут подаваться записи другого регистра накопления , например, "Продажи",
имеющего другую структуру измерений и ресурсов.
Решение должно содержать примитивный пользовательский интерфейс для проверки, позволяющий задать параметры функции и продемонстрировать результат.
Решил сюда выкинуть, может у кого -то появятся мыслишки по решению. Условие пишу как есть:
Необходимо реализовать универсальную функцию вида: СкорректироватьЗаписи(ИмяРегистра, ИсходныеДвижения, ЦелевыеДвижения).
Где ИмяРегистра - имя регистра накопления (строка);
ИсходныеДвижения - набор исходных движений (тип - Таблица значений)
ЦелевыеДвижения - набор целевых движений (тип - Таблица значений)
Функция должна возвращать набор записей соответствующего регистра (в виде таблицы значений), при записи котрого (в рамках данной задачи запись реализовывать не надо) в системе будут целевые движения. Исходные движения при этом не удаляются.
Например, существует движения регистра "Остатки номенклатуры", Исходные движения (Приходная №2):
Номенк Колво Сум
Kohinor 60 390
Паркер 40 3800
И есть движения регистра "Остатки номенклатуры", Целевые движения (Приходная №1):
Номенк Колво Сум
Kohinor 10 70
Паркер 10 1000
На выходе функция должна вернуть таблицу значений следующего вида:
Номенк Колво Сум
Kohinor -50 -320
Паркер -30 -2800
Функция должна быть универсальной, т.е. на вход могут подаваться записи другого регистра накопления , например, "Продажи",
имеющего другую структуру измерений и ресурсов.
Решение должно содержать примитивный пользовательский интерфейс для проверки, позволяющий задать параметры функции и продемонстрировать результат.
По теме из базы знаний
Найденные решения
Я так в свое время решал:
// Создадим итоговую таблицу, в которой найдем разницу
ИтоговаяТаблица = СоставПлана.Выгрузить();
// Вычитаем строки исходного плана(добавляем строки с минусом)
Для Каждого СтрокаТЗ Из ИсходнаяТаблица Цикл
НоваяСтрока = ИтоговаяТаблица.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТЗ);
НоваяСтрока.Количество = -СтрокаТЗ.Количество;// Тут нужно будет перечислить все ресурсы
КонецЦикла;
// Сформируем перечень полей по которым надо свернуть таблицу
КолонкиГруппировок = "Период, Подразделение, Номенклатура, ХарактеристикаНоменклатуры, ЕдиницаИзмерения, Коэффициент, Цена, СтавкаНДС, Заказ, Контрагент, Договор, Проект";// Тут все Измерения(Все колонки, кроме ресурсов)
КолонкиСуммирования = "Количество, СуммаНДС, Сумма";// Тут перечисляем все ресурсы
// Свернем итоговую таблицу, чтобы получить разницу
ИтоговаяТаблица.Свернуть(КолонкиГруппировок, КолонкиСуммирования);
// Уберем строки, в которых количество = 0 и Сумма = 0, ибо изменение цены, без изменения количества
// Только 0 количество
Отбор = Новый Структура("Количество", 0);
МассивСтрокНаУдаление = ИтоговаяТаблица.НайтиСтроки(Отбор);
Для Каждого СтрокаТЗ Из МассивСтрокНаУдаление Цикл
ИтоговаяТаблица.Удалить(СтрокаТЗ);
КонецЦикла;
// Сортировать не обязательно
ИтоговаяТаблица.Сортировать("Период, Номенклатура, ХарактеристикаНоменклатуры, Количество");
Показать
(26) по запросу: в цикле конкатенацией строк. Это вообще не проблема.
по второму варианту: из метаданных полученные измерения и ресурсы собрать в отдельные массивы. Потом собрать в строку не составит проблем. В чем сложность?
Я привел примеры решений. Я не уговариваю использовать только запрос.
по второму варианту: из метаданных полученные измерения и ресурсы собрать в отдельные массивы. Потом собрать в строку не составит проблем. В чем сложность?
Я привел примеры решений. Я не уговариваю использовать только запрос.
Остальные ответы
Подписаться на ответы
Инфостарт бот
Сортировка:
Древо развёрнутое
Свернуть все
(1) постановка задачи, какая-то дибильная.
Но по факту, как я понял,
интерактивно пользователь вбивает целевые движения, т.е. то, что должно после операции остаться.
А значит, делаем срез остатков, и обычной формулой рассчитывааем Целевое-Исходное= ТоЧтоНужно.
А универсальный запрос сделать просто,
(3)
Имя регистра, подменяй только методом СтрЗаменить
Потом выполнить выгрузить, и обходишь колонки и строки таблицы значений, как нужно
Но по факту, как я понял,
интерактивно пользователь вбивает целевые движения, т.е. то, что должно после операции остаться.
А значит, делаем срез остатков, и обычной формулой рассчитывааем Целевое-Исходное= ТоЧтоНужно.
А универсальный запрос сделать просто,
(3)
"ВЫБРАТЬ *
|ИЗ
| РегистрНакопления.ИмяРегистра.Остатки КАК РегистрОстатки"
Имя регистра, подменяй только методом СтрЗаменить
Потом выполнить выгрузить, и обходишь колонки и строки таблицы значений, как нужно
(9) я и написал, что формулировка задачи не совсем понятная. Как я понял, так и написал.
Если речь не о корректировке остатка, а сторнировании движения,
то точно также, не вижу проблем, немного видоизменить мой запрос, только выбрать другую таблицу регистра, все поля, и по регистратору отобрать. Только в параметрах функции у вас регистратора то нет. Откуда она узнает о каком исходном документе речь.
А так задача, сама по себе, проста и незатейлива...
А если параметры движения, это уже движения исходного документа, то и запрос никакой не нужен, просто анализируйте их и все.
Если речь не о корректировке остатка, а сторнировании движения,
то точно также, не вижу проблем, немного видоизменить мой запрос, только выбрать другую таблицу регистра, все поля, и по регистратору отобрать. Только в параметрах функции у вас регистратора то нет. Откуда она узнает о каком исходном документе речь.
А так задача, сама по себе, проста и незатейлива...
А если параметры движения, это уже движения исходного документа, то и запрос никакой не нужен, просто анализируйте их и все.
(16) несколько вариантов.
1. Можно через загрузку обеих ТЗ в запрос. Соединение, группировка по измерениям. Вычитание.
2. Можно без запроса. Инвертировать ресурсы первой таблицы (создать локальную ТЗ). Объединить обе ТЗ в одну результирующую. Результирующую свернуть по измерениям и суммированием ресурсов.
1. Можно через загрузку обеих ТЗ в запрос. Соединение, группировка по измерениям. Вычитание.
2. Можно без запроса. Инвертировать ресурсы первой таблицы (создать локальную ТЗ). Объединить обе ТЗ в одну результирующую. Результирующую свернуть по измерениям и суммированием ресурсов.
(18)
Возьмём запрос. Структура каждый раз разная, как собрать запрос, как описать поля? В цикле по измерениям и ресурсам? А потом как дать запросу понять какие поля группировать, а какие складывать? Возьмём второй вариант: чтобы свернуть, нужно опять в цикле описывать строку ,состоящая из полей, по которым будем сворачивать, и строку, с теми полями которые будут сворачиваться.
Возьмём запрос. Структура каждый раз разная, как собрать запрос, как описать поля? В цикле по измерениям и ресурсам? А потом как дать запросу понять какие поля группировать, а какие складывать? Возьмём второй вариант: чтобы свернуть, нужно опять в цикле описывать строку ,состоящая из полей, по которым будем сворачивать, и строку, с теми полями которые будут сворачиваться.
(29) А передача ТЗ в СУБД? А получение результата от СУБД? Особенно если таблицы большие? А накладные расходы на вызовы СУБД? Ради чего? Когда уже все вот оно и все можно легко сделать даже не трогая сетку, не говоря уже о цельном сервере баз данных?
Для меня это такой же нонсенс, как если бы всерьез предлагали для сложения двух чисел дергать сиквел, чтобы это сделал он. Да, работать будет. Можно еще веб-сервис для этого написать. Тоже рабочее решение. И очень гибкое. Чем не вариант?
Для меня это такой же нонсенс, как если бы всерьез предлагали для сложения двух чисел дергать сиквел, чтобы это сделал он. Да, работать будет. Можно еще веб-сервис для этого написать. Тоже рабочее решение. И очень гибкое. Чем не вариант?
(30) в любом случае будут накладные расходы. ТЗ сама по себе высоконагруженная сущность. Без запроса нужна еще одна ТЗ. Результирующая ТЗ будет удвоена. Если ТЗ большая, то индексировать не помешает.
Что будет менее нагрузочным и быстрым нужно смотреть уже по факту использования. Как правило для sql выделяется больше ресурсов.
Что будет менее нагрузочным и быстрым нужно смотреть уже по факту использования. Как правило для sql выделяется больше ресурсов.
(31) Передача в СУБД для экономии ОЗУ на обработке результирующей таблицы? Интересная идея :) Только не взлетит. Для сериализации и передачи в СУБД большой таблицы тоже потребуются дополнительные ресурсы.
В общем, раз консенсуса нет - не вижу смысла продолжать эту тему. Я чувствую себя нелепо, пытаясь доказывать аксиоматичные для меня вещи.
В общем, раз консенсуса нет - не вижу смысла продолжать эту тему. Я чувствую себя нелепо, пытаясь доказывать аксиоматичные для меня вещи.
(26) по запросу: в цикле конкатенацией строк. Это вообще не проблема.
по второму варианту: из метаданных полученные измерения и ресурсы собрать в отдельные массивы. Потом собрать в строку не составит проблем. В чем сложность?
Я привел примеры решений. Я не уговариваю использовать только запрос.
по второму варианту: из метаданных полученные измерения и ресурсы собрать в отдельные массивы. Потом собрать в строку не составит проблем. В чем сложность?
Я привел примеры решений. Я не уговариваю использовать только запрос.
(28)ясно, приму как решение. Поясню, задача предлагалась как тестовый пример на собеседовании. Время на решение не более 30 минут с реализацией интерфейса. Просто показалась, что заниматься на собеседовании за 30 минут собиранием строки не лучшей идей. Вот и выложил сюда. Спасибо
(33) то что это тестовое задание было сразу понятно.
А вот то что его нужно было решить прямо на собеседовании в коде за 30 мин. Лучше не рассматривать как вариант будущей работы там.
На собеседовании можно описать алгоритм и/или потом решить высланное тестовое задание. Это нормально.
А вот то что его нужно было решить прямо на собеседовании в коде за 30 мин. Лучше не рассматривать как вариант будущей работы там.
На собеседовании можно описать алгоритм и/или потом решить высланное тестовое задание. Это нормально.
(34)
Ну почему же? Мне наоборот - очень понравилось. 30 мин на такую задачку - это с запасом на мандраж, тупняк и чаю попить.
А возможность посмотреть на живой код с гарантией авторства и тут же задать вопросы по нему - бесценно.
Задачка с одной стороны - простейшая алгоритмистика, с другой - нужно хотя бы знать про метаданные :)
Если отдать эту примитивную задачку "на потом", то так и не узнаешь, что чувак на месте не смог бы решить ее за полчаса самостоятельно (что сразу бы сказало о крайне ограниченной практике программирования).
Задачи на "домашнее задание" - это уже другой класс задач. Где обычно проверяется не только элементарное умение кодить, но и какое-то элементарное понимание учета.
А вот то что его нужно было решить прямо на собеседовании в коде за 30 мин. Лучше не рассматривать как вариант будущей работы там.
Ну почему же? Мне наоборот - очень понравилось. 30 мин на такую задачку - это с запасом на мандраж, тупняк и чаю попить.
А возможность посмотреть на живой код с гарантией авторства и тут же задать вопросы по нему - бесценно.
Задачка с одной стороны - простейшая алгоритмистика, с другой - нужно хотя бы знать про метаданные :)
Если отдать эту примитивную задачку "на потом", то так и не узнаешь, что чувак на месте не смог бы решить ее за полчаса самостоятельно (что сразу бы сказало о крайне ограниченной практике программирования).
Задачи на "домашнее задание" - это уже другой класс задач. Где обычно проверяется не только элементарное умение кодить, но и какое-то элементарное понимание учета.
(9) да и вообще, если вчитаться...
то параметры функции уже таблицы значений и исходные и целевые..
а значит, нам вообще никакой запрос точно не нужен.
Просто сравниваем 2 таблицы значений,
и создаем набор записей, от нужного регистра по имени, в него и загружаем эту таблицу значений
то параметры функции уже таблицы значений и исходные и целевые..
а значит, нам вообще никакой запрос точно не нужен.
Просто сравниваем 2 таблицы значений,
и создаем набор записей, от нужного регистра по имени, в него и загружаем эту таблицу значений
(3) Если таблицы повторяют структуру регистра, то циклом по колонкам определяем типы, если тип числовой - это ресурс, схему запроса, думаю, привлекать не будем, из имен колонок формируем секцию ВЫБРАТЬ, передаем таблицу целевых движений в параметры запроса, на выходе получаем таблицу необходимых движений.
В качестве параметров нужно передавать, какие колонки таблицы являются ресурсами, или же в функции придется анализировать, обращаясь к метаданным, что в этих колонках ресурсы - их вычитаем, в этих - измерения - по ним группируем.
Задача нахождения разницы решается "вычитание" из одной таблицы в другую. Языком запросов - это объединение с последующей группировкой по ключевым полям - измерениям.
Задача нахождения разницы решается "вычитание" из одной таблицы в другую. Языком запросов - это объединение с последующей группировкой по ключевым полям - измерениям.
Я так в свое время решал:
// Создадим итоговую таблицу, в которой найдем разницу
ИтоговаяТаблица = СоставПлана.Выгрузить();
// Вычитаем строки исходного плана(добавляем строки с минусом)
Для Каждого СтрокаТЗ Из ИсходнаяТаблица Цикл
НоваяСтрока = ИтоговаяТаблица.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТЗ);
НоваяСтрока.Количество = -СтрокаТЗ.Количество;// Тут нужно будет перечислить все ресурсы
КонецЦикла;
// Сформируем перечень полей по которым надо свернуть таблицу
КолонкиГруппировок = "Период, Подразделение, Номенклатура, ХарактеристикаНоменклатуры, ЕдиницаИзмерения, Коэффициент, Цена, СтавкаНДС, Заказ, Контрагент, Договор, Проект";// Тут все Измерения(Все колонки, кроме ресурсов)
КолонкиСуммирования = "Количество, СуммаНДС, Сумма";// Тут перечисляем все ресурсы
// Свернем итоговую таблицу, чтобы получить разницу
ИтоговаяТаблица.Свернуть(КолонкиГруппировок, КолонкиСуммирования);
// Уберем строки, в которых количество = 0 и Сумма = 0, ибо изменение цены, без изменения количества
// Только 0 количество
Отбор = Новый Структура("Количество", 0);
МассивСтрокНаУдаление = ИтоговаяТаблица.НайтиСтроки(Отбор);
Для Каждого СтрокаТЗ Из МассивСтрокНаУдаление Цикл
ИтоговаяТаблица.Удалить(СтрокаТЗ);
КонецЦикла;
// Сортировать не обязательно
ИтоговаяТаблица.Сортировать("Период, Номенклатура, ХарактеристикаНоменклатуры, Количество");
Показать
Я бы делал так (никаких запросов - меня вообще раздражает, когда шурупы забивают молотком, просто потому что уже научились забивать им гвозди):
- определил по метаданным и имени регистра поля ресурсов и измерений
- слил таблицы в одну (исходные движения - с минусом по ресурсам)
- свернул таблицу по измерениям (суммируя по полям ресурсов)
- удалил строки с нулевыми значениями всех ресурсов
- вернул получившуюся таблицу
ЗЫ. Собственно, в (22) именно так и сделано
- определил по метаданным и имени регистра поля ресурсов и измерений
- слил таблицы в одну (исходные движения - с минусом по ресурсам)
- свернул таблицу по измерениям (суммируя по полям ресурсов)
- удалил строки с нулевыми значениями всех ресурсов
- вернул получившуюся таблицу
ЗЫ. Собственно, в (22) именно так и сделано
Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот