Есть красивая задача с элегантным решением. Делюсь, разомните мозги. Первый, кто решит еще и 1СМ получит в качестве награды за интеллект..

Есть некоторый иерархический справочник, иерархия элементов. У каждого элемента есть поле «Позиция» (может быть дробным и отрицательным). Элементы в пределах одного родителя должны быть пронумерованы в поле «Позиция» по порядку с единицы с шагом один: 1, 2, … N

Таким образом, например, чтобы поменять порядок элементов с позициями 2 и 3 мы можем элементу с позицией 2 установить позицию 2,5 и вызвать процедуру исправления порядка.

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

Пример: в группе с названием Алкоголь есть элементы с позициями:

Пиво 1
Водка 2
Эль 3
Я меняю:

Пиво 2.5
Водка 2
Эль 3
Система должна пересчитать по всей номенклатуре и сделать:

Водка 1
Пиво 2
Эль 3
Причем найти отклонения и сделать изменения максимально эффективно.

По сути можно упростить вопрос — как запросом найти группы, где порядок 1, 2, … N нарушен?

Вот еще пример:

Есть группа Алкоголь 1, в ней элементы:
Водка 2
Пиво 2.5
Эль 3
Есть группа Мясное 2, в ней элементы:
Сосиски 3
Ветчина 5
Есть группа Напитки 3, в ней элементы:
Квас 1
Сок 2

Нужно по этому пример найти запросом группы, где нарушен порядок 1, 2, N.
Правильный ответ: Алкоголь, Мясное.
Неправильные ответы: Напитки, Корень.
---
Задачу уже решили на Мисте.
Потому снимаю вознаграждение.
Вот решение:

```1c
    Функция УточнитьПорядокЗадач()
    З = Новый Запрос(
    "ВЫБРАТЬ
    | Т.Родитель КАК Родитель,
    | КОЛИЧЕСТВО(*) КАК Количество,
    | СУММА(Т.Позиция) КАК СуммаПозиции
    |ПОМЕСТИТЬ ТГруппы
    |ИЗ
    | Справочник.БС_Задачи КАК Т
    |
    |СГРУППИРОВАТЬ ПО
    | Т.Родитель
    |
    |ИМЕЮЩИЕ
    | (1 + КОЛИЧЕСТВО(*)) * КОЛИЧЕСТВО(*) / 2 <> СУММА(Т.Позиция)
    |;
    |
    |////////////////////////////////////////////////////////////­////////////////////
    |ВЫБРАТЬ
    | Т.Ссылка КАК Ссылка,
    | Т.Ссылка.Позиция КАК Позиция,
    | Т.Родитель КАК Родитель
    |ИЗ
    | Справочник.БС_Задачи КАК Т
    | ВНУТРЕННЕЕ СОЕДИНЕНИЕ ТГруппы КАК ТГРуппы
    | ПО Т.Родитель = ТГРуппы.Родитель
    |
    |УПОРЯДОЧИТЬ ПО
    | Позиция
    |ИТОГИ ПО
    | Родитель");
    Выборка = З.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
    Пока Выборка.Следующий() Цикл
    ВыборкаПозиций = Выборка.Выбрать();
    Позиция = 0;
    ;//Сообщить("Проверем группу: " + Выборка.Родитель);
    Пока ВыборкаПозиций.Следующий() Цикл
    Позиция = Позиция + 1;
    //Если позиция поменялась, тогда записываем
    Если ВыборкаПозиций.Позиция <> Позиция Тогда
    ;//Сообщить(" + ВыборкаПозиций.Ссылка + ": "+ ВыборкаПозиций.Позиция + " -> " + Позиция);
    ОО = ВыборкаПозиций.Ссылка.ПолучитьОбъект();
    ОО.Позиция = Позиция;
    ОО.Записать();
    КонецЕсли;
    КонецЦикла;

    КонецЦикла;
    КонецФункции
```
---
этот алгоритм есть в каждом коммунальном биллинге с маршрутами раздачи квитанций
---
не нужно лишних аналогий. Просто озвучьте принцип.
---
Сообщение было скрыто модератором.
---
Задачу уже решили на Мисте.
Потому снимаю вознаграждение.
Вот решение:

```1c
    Функция УточнитьПорядокЗадач()
    З = Новый Запрос(
    "ВЫБРАТЬ
    | Т.Родитель КАК Родитель,
    | КОЛИЧЕСТВО(*) КАК Количество,
    | СУММА(Т.Позиция) КАК СуммаПозиции
    |ПОМЕСТИТЬ ТГруппы
    |ИЗ
    | Справочник.БС_Задачи КАК Т
    |
    |СГРУППИРОВАТЬ ПО
    | Т.Родитель
    |
    |ИМЕЮЩИЕ
    | (1 + КОЛИЧЕСТВО(*)) * КОЛИЧЕСТВО(*) / 2 <> СУММА(Т.Позиция)
    |;
    |
    |////////////////////////////////////////////////////////////­////////////////////
    |ВЫБРАТЬ
    | Т.Ссылка КАК Ссылка,
    | Т.Ссылка.Позиция КАК Позиция,
    | Т.Родитель КАК Родитель
    |ИЗ
    | Справочник.БС_Задачи КАК Т
    | ВНУТРЕННЕЕ СОЕДИНЕНИЕ ТГруппы КАК ТГРуппы
    | ПО Т.Родитель = ТГРуппы.Родитель
    |
    |УПОРЯДОЧИТЬ ПО
    | Позиция
    |ИТОГИ ПО
    | Родитель");
    Выборка = З.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
    Пока Выборка.Следующий() Цикл
    ВыборкаПозиций = Выборка.Выбрать();
    Позиция = 0;
    ;//Сообщить("Проверем группу: " + Выборка.Родитель);
    Пока ВыборкаПозиций.Следующий() Цикл
    Позиция = Позиция + 1;
    //Если позиция поменялась, тогда записываем
    Если ВыборкаПозиций.Позиция <> Позиция Тогда
    ;//Сообщить(" + ВыборкаПозиций.Ссылка + ": "+ ВыборкаПозиций.Позиция + " -> " + Позиция);
    ОО = ВыборкаПозиций.Ссылка.ПолучитьОбъект();
    ОО.Позиция = Позиция;
    ОО.Записать();
    КонецЕсли;
    КонецЦикла;

    КонецЦикла;
    КонецФункции
```