Всем привет!
Стоит такая задачка:
Наборы товаров по две номенклатуры выводятся в табличную часть, но есть дубли в формате:
"Товар1" - "Товар2"
"Товар2" - "Товар1"
Подскажите, как можно от этого избавиться?
Код формирования таблицы значений:

```1c
    Процедура СформироватьНаСервере(ВыбранныйСклад)
    // Получаем список товаров на выбранном складе
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
    | КоличествоТоваровНаСкладахОстатки.Товар.Артикул КАК Артикул,
    | КоличествоТоваровНаСкладахОстатки.Товар.Себестоимость КАК Себестоимость,
    | КоличествоТоваровНаСкладахОстатки.Товар КАК Товар,
    | КоличествоТоваровНаСкладахОстатки.Склад КАК Склад,
    | КоличествоТоваровНаСкладахОстатки.КоличествоОстаток КАК Количество
    |ИЗ
    | РегистрНакопления.КоличествоТоваровНаСкладах.Остатки КАК КоличествоТоваровНаСкладахОстатки
    |ГДЕ
    | КоличествоТоваровНаСкладахОстатки.Склад = &Склад
    | И КоличествоТоваровНаСкладахОстатки.КоличествоОстаток > 0";

    Запрос.УстановитьПараметр("Склад", ВыбранныйСклад);
    ТоварыНаСкладе = Запрос.Выполнить().Выгрузить();

    // Создаем таблицу для хранения наборов товаров
    НаборыТоваров = Новый ТаблицаЗначений;
    НаборыТоваров.Колонки.Добавить("Товар1");
    НаборыТоваров.Колонки.Добавить("Артикул1");
    НаборыТоваров.Колонки.Добавить("Товар2");
    НаборыТоваров.Колонки.Добавить("Артикул2");
    НаборыТоваров.Колонки.Добавить("КоличествоНаборов");
    НаборыТоваров.Колонки.Добавить("Себестоимость");

    // Проходим по всем товарам на складе
    Для Каждого Товар1 Из ТоварыНаСкладе Цикл
    Для Каждого Товар2 Из ТоварыНаСкладе Цикл
    // Проверяем, что это разные товары и они доступны на складе
    Если Товар1.Товар <> Товар2.Товар И Товар1.Количество > 0 И Товар2.Количество > 0 Тогда
    // Получаем артикулы товаров
    Артикул1 = Товар1.Товар.Артикул;
    Артикул2 = Товар2.Товар.Артикул;

    // Вычисляем степень схожести артикулов
    МаксимальнаяДлинаАртикула = Макс(СтрДлина(Артикул1), СтрДлина(Артикул2));
    СтепеньСхожести = 0;
    Для Индекс = 1 По МаксимальнаяДлинаАртикула Цикл
    Если Лев(Артикул1, Индекс) = Лев(Артикул2, Индекс) Тогда
    СтепеньСхожести = Индекс;
    Иначе
    Прервать;
    КонецЕсли;
    КонецЦикла;

    // Если степень схожести > 0, то добавляем набор товаров в таблицу
    Если СтепеньСхожести > 0 Тогда
    Количество = Мин(Товар1.Количество, Товар2.Количество);
    Разница = Товар1.Себестоимость - Товар2.Себестоимость;
    Себестоимость = Макс(-Разница, Разница);
    НаборТоваров = Новый Структура("Артикул1, Артикул2, КоличествоНаборов, Себестоимость, Товар1, Товар2", Товар1.Товар.Артикул, Товар2.Товар.Артикул, Количество, Себестоимость, Товар1.Товар, Товар2.Товар);
    //НаборТоваров.Товар1 = Товар1.Товар;
    //НаборТоваров.Товар2 = Товар2.Товар;
    //НаборТоваров.КоличествоНаборов = Мин(Товар1.Количество, Товар2.Количество);

    // Проверяем, что такой набор еще не был добавлен в таблицу
    Дубль = Новый Структура("Артикул1, Артикул2, КоличествоНаборов, Себестоимость, Товар1, Товар2", Товар2.Товар.Артикул, Товар1.Товар.Артикул, Количество, Себестоимость, Товар2.Товар, Товар1.Товар);
    Если НаборыТоваров.Найти(НаборТоваров) = Неопределено И НаборыТоваров.Найти(Дубль) = Неопределено Тогда
    //НаборыТоваров.Добавить(НаборТоваров);
    //Для Каждого КлючЗначение из НаборТоваров Цикл
    // НаборыТоваров.Колонки.Добавить(КлючЗначение.Товар1);
    // НаборыТоваров.Колонки.Добавить(КлючЗначение.Товар2);
    // НаборыТоваров.Колонки.Добавить(КлючЗначение.Количество);
    //КонецЦикла;

    ЗаполнитьЗначенияСвойств(НаборыТоваров.Добавить(), НаборТоваров);
    КонецЕсли;
    КонецЕсли;
    КонецЕсли;
    КонецЦикла;
    КонецЦикла;

    ТабличнаяЧасть = Объект.Наборы;
    ТабличнаяЧасть.Очистить();
    Для Каждого Строка2 Из НаборыТоваров Цикл
    Строка = ТабличнаяЧасть.Добавить();
    Строка.Товар1 = Строка2.Товар1;
    Строка.Товар2 = Строка2.Товар2;
    Строка.Кол_во = Строка2.КоличествоНаборов;
    КонецЦикла;
    КонецПроцедуры
```

Ниже скриншот того, как это выглядит
---
```1c
    Если НаборыТоваров.НайтиСтроки(новый Структура("Товар1, Товар2",Товар1.Товар,Товар2.Товар)).Количество() ИЛИ
    НаборыТоваров.НайтиСтроки(новый Структура("Товар2, Товар1",Товар1.Товар,Товар2.Товар)).Количество() Тогда
    ПРОДОЛЖИТЬ;
    КонецЕсли;
```
---
```1c
    Если НаборыТоваров.НайтиСтроки(новый Структура("Товар1, Товар2",Товар1.Товар,Товар2.Товар)).Количество() ИЛИ
    НаборыТоваров.НайтиСтроки(новый Структура("Товар2, Товар1",Товар1.Товар,Товар2.Товар)).Количество() Тогда
    ПРОДОЛЖИТЬ;
    КонецЕсли;
```
---
Спасибо, добрый человек!
---
Первый товар из списка надо соединить со всеми, кроме первого? Второй - со всеми, кроме первого и второго? И т.д. Я правильно понял?

```1c
    Для Первый = 0 По ТоварыНаСкладе.Количество() - 2 Цикл
    Для Второй = Первый + 1 По ТоварыНаСкладе.Количество() - 1 Цикл
    НовыйНабор = НаборыТоваров.Добавить();
    НовыйНабор.Товар1 = ТоварыНаСкладе[Первый].Товар;
    НовыйНабор.Артикул1 = ТоварыНаСкладе[Первый].Артикул;
    НовыйНабор.Товар2 = ТоварыНаСкладе[Второй].Товар;
    НовыйНабор.Артикул2 = ТоварыНаСкладе[Второй].Артикул;
    КонецЦикла;
    КонецЦикла;
```
---
```1c
    WITH vt_data as (
    sel ect 'Товар1' as nom, 1 as k
    UNI ON ALL select 'Товар2', 2
    UNI ON ALL select 'Товар3', 3
    UNION ALL sel ect 'Товар4', 4
    )

    SEL ECT
    t1.nom as nom1
    ,t2.nom as nom2
    ,t1.k as k1
    ,t2.k as k2
    FR OM
    vt_data as t1
    INNER JOIN vt_data as t2
    on t1.nom < t2.nom
```

Результат:
```1c
    nom1 nom2 k1 k2
    Товар1 Товар2 1 2
    Товар1 Товар3 1 3
    Товар1 Товар4 1 4
    Товар2 Товар3 2 3
    Товар2 Товар4 2 4
    Товар3 Товар4 3 4
```
---
На сколько я понимаю нужны пары каждый с каждым, но один раз и не с собой. Запросом это делается одним соединением.
А куча вложенных циклов и т.д. было когда была 1С 77. Не было там запросов, по большому счету. Были полноценные запросы в 1С++ 77, но таких сейчас и в 1С 8.3 нет.