Имя: Пароль:
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.НоваяКолонка("НомерСтрокиТЗ");


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