Имя: Пароль:
1C
1C 7.7
v7: Объединить две ТЗ
0 Arbuz
 
31.01.19
15:18
Есть две ТЗ. Состав колонок совпадает частично. В ТЗ_2 есть колонка "Ключ" с уникальным натуральным числовым значением, напр 4 строки - "2,3,7,100". Нужно в ТЗ_1 заменить значения в совпадающих по имени колонках из ТЗ_2, где номер строки ТЗ_1 = значению Ключ ТЗ_2. Удалить строки ТЗ_1, номера которых нет в колонке Ключ ТЗ_2. Добавить в ТЗ_1 строки из ТЗ_2, где Ключ > начального количества строк ТЗ_1.
dbf, 1cpp, formex, 1sqlite
Пока что в голову ничего лучше, кроме двойного прохода с промежуточной ТЗ_3 не приходит.
1 VladZ
 
31.01.19
15:30
Вот тут почитай: http://www.1cpp.ru/docum/html/IndexedTable.html
2 VladZ
 
31.01.19
15:31
Вариант №2: сразу получать данные в нужном виде.
3 Arbuz
 
31.01.19
15:37
(1) Почитал. Не просветляет. Что, надо будет получать разность, потом пересечение и объединять?
4 Arbuz
 
31.01.19
15:39
(2) Сразу никак, данные из разных источников, полученные в разное время
5 VladZ
 
31.01.19
15:50
(3) Почитай про ВнутреннееСоединение и ЛевоеСоединение.
6 Arbuz
 
31.01.19
15:53
(5) Воу! спс, у меня локально какие-то старинные доки на ИТЗ
7 Kigo_Kigo
 
31.01.19
16:21
(5) А ничего что это клюшки?
8 Evgenchik
 
31.01.19
16:23
(7) Ничего
9 trad
 
31.01.19
16:27
(7) на клюшки ТС наложены магические руны
10 Svetka
 
31.01.19
18:08
(0) Да, без промежуточной ТЗ и перебора тз1 и тз2 - никак, только если извлекать данные в ключ как - то иначе.    


        ТЗ3 =СоздатьОбъект("ТаблицаЗначений");
    ТЗ3.Очистить();
    ТЗ3.НоваяКолонка("строкаТЗ1");
    
    ТЗ2.ВыбратьСтроки();
    Пока ТЗ2.ПолучитьСтроку()= 1 Цикл
        НомСтр_тз1 = ТЗ2.Ключ;
        
        Числ = СтрЧислоВхождений(СокрЛП(НомСтр_тз1),",");
        Вх1   = Найти(СокрЛП(НомСтр_тз1),",");
        Для в= 1 По Числ+1 Цикл
            НомПл="";
            Если в=1 Тогда
                НомПл = Число(Лев(СокрЛП(НомСтр_тз1),Вх1-1));
                Ост   = Сред(СокрЛП(НомСтр_тз1),Вх1+1);
                Вх1   = Найти(СокрЛП(Ост),",");
            ИначеЕсли в=Числ+1 Тогда
                НомПл = Число(Сред(СокрЛП(Ост),Вх1+1));
            Иначе
                НомПл = Число(Лев(СокрЛП(Ост),Вх1-1));
                Ост   = Сред(СокрЛП(Ост),Вх1+1);
                Вх1   = Найти(СокрЛП(Ост),",");
            КонецЕсли;                        
            
            ТЗ3.НоваяСтрока();
            ТЗ3.строкаТЗ1 = НомПл;
            
            Если ТЗ1.ПолучитьСтрокуПоНомеру(НомПл) = 1 Тогда
                //строка найдена
                  ТЗ1.Колонка1 = ТЗ2.Колонка1;
                ТЗ1.Колонка2 = ТЗ2.Колонка2;
                ТЗ1.КолонкаN = ТЗ2.КолонкаN;
            Иначе
                Если ТЗ1.КоличествоСтрок()<НомПл Тогда
                    //строка создается
                    ТЗ1.НоваяСтрока();
                    ТЗ1.Колонка1 = ТЗ2.Колонка1;
                    ТЗ1.Колонка2 = ТЗ2.Колонка2;
                    ТЗ1.КолонкаN = ТЗ2.КолонкаN;
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;

    ТЗ1.ВыбратьСтроки();    
    Пока ТЗ1.ПолучитьСтроку() = 1 Цикл
        ~метка:
        стр = "";
        Если ТЗ3.НайтиЗначение(ТЗ1.НомерСтроки,стр,"строкаТЗ1") = 0 Тогда
            //строка удаляется
            ТЗ1.УдалитьСтроку();
            Если ТЗ1.НомерСтроки <> 0 Тогда
                Перейти ~метка;
            КонецЕсли;
        КонецЕсли;    
    КонецЦикла;
11 Arbuz
 
31.01.19
18:17
(10) Зря вы так. Все получилось через ИТЗ.ПравоеСоединение. 30 строк кода. И то из-за того, что пришлось извратиться с циклом по первой ИТЗ для ЗаполнитьКолонку("НомерСтроки"). На таблицах до десятка тысяч строк - до полутора сотен мсек.
12 VladZ
 
31.01.19
18:26
(10) Однако! Использование меток - дурной тон.

В данном случае достаточно было использовать "Продолжить"
13 Aleksandr N
 
31.01.19
19:01
(12) А в семерке оно есть? А то я не умею в 7.7.
14 Arbuz
 
01.02.19
11:46
(13) конечно есть

(0) кому интересно получилось так:



    _ф = _getPerformanceCounter();
    
    _ИТЗ1 = СоздатьОбъект("ИндексированнаяТаблица");
    _ИТЗ1.Загрузить(ТЗ1);
    _ИТЗ2 = СоздатьОбъект("ИндексированнаяТаблица");
    _ИТЗ2.Загрузить(ТЗ2);
    _ИТЗ2.ДобавитьИндекс("НомерСтрокиТЗ", "Ключ");
    
    _аВрем = "";
    _СчетчикЦикла = 0;
    Для _СчетчикЦикла = 1 По _ИТЗ1.КоличествоСтрок() Цикл
        _аВрем = _аВрем + _СчетчикЦикла + ",";
    КонецЦикла;
    Если _аВрем = "" Тогда глОтладка("Пустая ИТЗ1"); Возврат; КонецЕсли;
    _КоличествоСтрокТЗ = СоздатьОбъект("СписокЗначений");
    _КоличествоСтрокТЗ.ИзСтрокиСРазделителями(Лев(_аВрем, СтрДлина(_аВрем) - 1));
    _ИТЗ1.ЗаполнитьКолонку(, "НомерСтрокиТЗ", _КоличествоСтрокТЗ);
    _КоличествоСтрокТЗ = "";
    
    _СтрокаКолонокТЗ = "";
    _СчетчикЦикла = 0;
    Для _СчетчикЦикла = 1 По СписокКолонокТаблицы.РазмерСписка() Цикл
         _КодКолонки = СписокКолонокТаблицы.ПолучитьЗначение(_СчетчикЦикла);
         Если глПроверкаКолонки(_КодКолонки, ВидКолонки, 1) = 1 Тогда
            _СтрокаКолонокТЗ = _СтрокаКолонокТЗ + _КодКолонки + ",";
         КонецЕсли;
    КонецЦикла;
    Если _СтрокаКолонокТЗ = "" Тогда глОтладка("Нет колонок"); Возврат; КонецЕсли;
    _СтрокаКолонокТЗ = Лев(_СтрокаКолонокТЗ, СтрДлина(_СтрокаКолонокТЗ) - 1);
    
    _ИТЗ1.ПравоеСоединение("НомерСтрокиТЗ", _ИТЗ2, "НомерСтрокиТЗ", _СтрокаКолонокТЗ);
    
    _ИТЗ2.Выгрузить(ТЗ1);
    
    _ИТЗ1 = ""; _ИТЗ2 = "";
    
    глОтладка(_GetPerformanceCounter() - _ф);
    


Вот бы ещё от цикла по ИТЗ1 избавиться.
Индекс по умолчанию как раз по номеру строки есть, но вот задать "НомерСтроки" в первом параметре Join'а нельзя к сожалению.
15 Arbuz
 
01.02.19
11:52
+(14) упс.


_ИТЗ1.Выгрузить(ТЗ1);


конечно же
16 MadDAD
 
01.02.19
13:16
(15) А если вот это:
[code]
  Для _СчетчикЦикла = 1 По _ИТЗ1.КоличествоСтрок() Цикл
        _аВрем = _аВрем + _СчетчикЦикла + ",";
    КонецЦикла;
    Если _аВрем = "" Тогда глОтладка("Пустая ИТЗ1"); Возврат; КонецЕсли;
    _КоличествоСтрокТЗ = СоздатьОбъект("СписокЗначений");
    _КоличествоСтрокТЗ.ИзСтрокиСРазделителями(Лев(_аВрем, СтрДлина(_аВрем) - 1));
    _ИТЗ1.ЗаполнитьКолонку(, "НомерСтрокиТЗ", _КоличествоСтрокТЗ);
    _КоличествоСтрокТЗ = "";
[/code]

заменить на это?
[code]
_ИТЗ1.ВыбратьСтроки()
Пока _ИТЗ1.ПолучитьСтроку() = 1 Цикл
        _ИТЗ1.НомерСтрокиТЗ = _ИТЗ1.НомерСтроки;
КонецЦикла;
[/code]
17 Arbuz
 
01.02.19
17:10
(16) Дык, собственно, это и было заменено в обратном порядке, для ускорения. Чтобы не перебирать в цикле строки ИТЗ. И в Вашем коде не хватает


_ИТЗ1.НоваяКолонка("НомерСтрокиТЗ");


перед циклом. Кстати в доках не документировано, что ЗаполнитьКолонку() создаёт её при отсутствии. Интересно, можно ли вообще избавиться от этого цикла?
Основная теорема систематики: Новые системы плодят новые проблемы.