Имя: Пароль:
1C
1С v8
А интересно как вы удаляете строки из таблицы значений.
,
0 Keyn
 
05.01.16
08:49
А интересно как вы удаляете строки из таблицы значений. Надеюсь что не так: ТаблицаЦен.Удалить(Индекс); (взял пример из хелпа)

Работать конечно будет просто медленно. Когда вы удаляете так как в хелпе, то 1Ска удалит строку и сдвинет остальные строки "вверх". А это медленный процесс. Если у вас большая таблица значений и удалить нужно много строк, это может занять время, а ждать не хочется, поэтому можно воспользоватся хитростью.

Добавляем в таблицу значений новую служебную колонку. В эту колонку каждому удаляемому значению ставим 1. Затем сортируем по этой колонке и все удаляемые значения окажутся в конце. (сортировка же делается быстро) Затем спокойно удаляем все начиная с конца, и в этом случае 1Ске не придется "сдвигать" строки. И такое удаление будет быстрым.

Вот такой код у меня получился:

// Очень быстро! Удаляет строки из таблицы значений, но только те строки в которых есть переданное значение
// ТЗ - таблица значений
// Колонка - идентификатор колонки в которой будет осуществлятся поиск Значения.
// Значение - значение которое будем удалять
// ЗначениеОставить - 1 означает что нужно оставить в таблице переднанное Значение, а остальные удалить
//                      0 наоборот, удалить из таблицы переданное Значение
Процедура УдалитьСтрокиИзТЗ(ТЗ,Колонка,Значение,ЗначениеОставить=0) Экспорт
    НадаУдалять=0;
    ТЗ.Колонки.Добавить("СЛУЖДЛЯУДАЛЕНИЯ");
    Если ЗначениеОставить=0 Тогда
        Для каждого СтрокаТЗ Из ТЗ Цикл
            Если СтрокаТЗ[Колонка]=Значение Тогда
                СтрокаТЗ.СЛУЖДЛЯУДАЛЕНИЯ=1;
                НадаУдалять=1;
            КонецЕсли;
        КонецЦикла;
    Иначе
        Для каждого СтрокаТЗ Из ТЗ Цикл
            Если СтрокаТЗ[Колонка]<>Значение Тогда
                СтрокаТЗ.СЛУЖДЛЯУДАЛЕНИЯ=1;
                НадаУдалять=1;
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
    
    Если НадаУдалять=1 Тогда
        ТЗ.Сортировать("СЛУЖДЛЯУДАЛЕНИЯ");
        Индекс=ТЗ.Количество()-1;
        
        Пока Индекс>=0 Цикл
            Если ТЗ[Индекс].СЛУЖДЛЯУДАЛЕНИЯ=1 Тогда
                ТЗ.Удалить(Индекс);
            Иначе
                Прервать;
            КонецЕсли;
            Индекс=Индекс-1;
        КонецЦикла;
    КонецЕсли;
    ТЗ.Колонки.Удалить("СЛУЖДЛЯУДАЛЕНИЯ");
    
КонецПроцедуры

писал код давно еще на заре выхода 8.0. и да  я знаю как пишется слово надо
1 Маратыч
 
05.01.16
08:51
А насколько быстрее, не замерялось? Чот терзают меня смутные сомнения, что весь этот комплект операций будет работать быстрее, чем некий "сдвиг" строк ТЗ в памяти при удалении через индекс.
2 Рэйв
 
05.01.16
08:52
у меня самый простой метод.Сначала нахожу все строки которые надо удалить и складываю их в список.
Потом пробегаю список и

Таб.Удалить(ЭлементСписка.Значение)
3 Рэйв
 
05.01.16
08:52
ну или если возможно одним условием, то получаю в массив через .НайтиСтроки()
4 Keyn
 
05.01.16
08:53
конечно же замерялось. к сожалению не могу привести сейчас ссылку. но этот способ один из быстрых. есть и другие)
5 tank68
 
05.01.16
09:25
Можно не в запрос передать таблицу как переменную

Ошибка = Ложь;
    Текст = "Загрузка почтовых ящиков, указанных сотрудниками на ВнешняяТаблицаДанных.";
    
    ЗапросПочтаНаВнешняяТаблицаДанных = Новый Запрос;
    ЗапросПочтаНаВнешняяТаблицаДанных.Текст =
        "ВЫБРАТЬ
        |    dbo_UserEmail.LDAP,
        |    ВЫБОР
        |        КОГДА ЕСТЬNULL(dbo_UserEmail.EMail1, ""0"") = ""0""
        |            ТОГДА ЕСТЬNULL(dbo_UserEmail.EMail2, ""0"")
        |        ИНАЧЕ ЕСТЬNULL(dbo_UserEmail.EMail1, ""0"")
        |    КОНЕЦ КАК ПочтаВнешняяТаблицаДанных
        |ИЗ
        |    ВнешнийИсточникДанных.Intraru.Таблица.dbo_UserEmail КАК dbo_UserEmail
        |ГДЕ
        |    ВЫБОР
        |            КОГДА ЕСТЬNULL(dbo_UserEmail.EMail1, ""0"") = ""0""
        |                ТОГДА ЕСТЬNULL(dbo_UserEmail.EMail2, ""0"")
        |            ИНАЧЕ ЕСТЬNULL(dbo_UserEmail.EMail1, ""0"")
        |        КОНЕЦ <> ""0""";
    
    ПочтаНаВнешняяТаблицаДанных = ЗапросПочтаНаВнешняяТаблицаДанных.Выполнить().Выгрузить();
            
    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    |    UserEmail.LDAP КАК LDAP,
    |    UserEmail.ПочтаВнешняяТаблицаДанных КАК ПочтаНаВнешняяТаблицаДанных
    |ПОМЕСТИТЬ ТаблицаСПочтой
    |ИЗ
    |    &UserEmail КАК UserEmail
    |
    |ИНДЕКСИРОВАТЬ ПО
    |    LDAP
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |    ФизическиеЛица.Ссылка,
    |    ТаблицаСПочтой.LDAP,
    |    ТаблицаСПочтой.ПочтаНаВнешняяТаблицаДанных
    |ИЗ
    |    Справочник.ФизическиеЛица КАК ФизическиеЛица
    |        ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаСПочтой КАК ТаблицаСПочтой
    |        ПО ФизическиеЛица.LDAP = ТаблицаСПочтой.LDAP
    |ГДЕ
    |    ТаблицаСПочтой.ПочтаНаВнешняяТаблицаДанных <> ФизическиеЛица.ЭлектроннаяПочтаВнешняяТаблицаДанных";
        
    Запрос.УстановитьПараметр("UserEmail",ПочтаНаВнешняяТаблицаДанных);
    Таблица = Запрос.Выполнить();
    Выборка = Таблица.Выбрать();
    
    #Если ТолстыйКлиентОбычноеПриложение Тогда
        Процессор = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
        Процессор.ОтображатьПроцентВывода = Истина;
        Процессор.НачатьВывод();
        Элемент = Новый ЭлементРезультатаКомпоновкиДанных;
    #КонецЕсли
        
    Колво = Выборка.Количество();
    НомерПП = 0;
    
    Пока Выборка.Следующий() Цикл
        Попытка
            
            НомерПП = НомерПП+1;
            #Если ТолстыйКлиентОбычноеПриложение Тогда
                Состояние(" Обрабатывается "+НомерПП+ " из "+Колво);             
                Элемент.ПроцентВывода = НомерПП/Колво*100;
                Процессор.ВывестиЭлемент(Элемент);             
            #КонецЕсли
            
            Если НомерПП = Цел(НомерПП/100)*100 Тогда
                Сообщить(""+ТекущаяДата()+" Обработано:"+СокрЛП(НомерПП));
            КонецЕсли;
            
            Об = Выборка.Ссылка.ПолучитьОбъект();
            Об.ЭлектроннаяПочтаВнешняяТаблицаДанных = Выборка.ПочтаНаВнешняяТаблицаДанных;
            Об.Записать();
        Исключение
            
            ТекстОшибки = (""+ТекущаяДата()+" Сотрудник "+СокрЛП(Выборка.Ссылка)+" почта на ВнешняяТаблицаДанных " + СокрЛП(Выборка.ПочтаНаВнешняяТаблицаДанных)+" ошибка: "+ОписаниеОшибки());
            Сообщить("--------------------------------------");
            Сообщить(ТекстОшибки,СтатусСообщения.ОченьВажное);
            Сообщить("--------------------------------------");
            Ошибка = Истина;
            Текст = Текст+Символы.ПС+Символы.ПС+ТекстОшибки;
            
        КонецПопытки;
        
        
        //Сообщить("Для сотрудника "+СокрЛП(Выборка.Ссылка)+" необходимо указать почту " + СокрЛП(Выборка.ПочтаНаВнешняяТаблицаДанных));
        
    КонецЦикла;    
    #Если Клиент Тогда
        Процессор.ЗакончитьВывод();
    #КонецЕсли
6 tank68
 
05.01.16
09:26
(5) А в запросе соответственно с этой таблицей что угодно делать, в запросе это быстрее делается чем в цикле
7 Маратыч
 
05.01.16
09:30
Костылестроение 80 лвл...
8 tank68
 
05.01.16
09:31
(7) Попробуй миллион строк перебрать в цикле и попробуй отобрать запросом я посмотрю как быстрее получиться
9 Мимохожий Однако
 
05.01.16
09:40
(0)важно для чего используется эта таблица значений потом. Может быть, в дальнейшем идёт перебор и достаточно поставить фильтр и продолжить для обработки. На просторах инета есть куча примеров. Я так и не понял, для чего создана ветка.
10 Маратыч
 
05.01.16
09:49
(8) От постановки задачи зависит. Я вообще постараюсь не допустить миллиона строк в ТЗ еще на этапе получения этих данных.
11 Euguln
 
05.01.16
10:09
(0) Забавно, а сортировка процесс на порядок сложнее, чем сдвиг строк. Об этом не задумывался?
12 SeraFim
 
05.01.16
10:20
Если есть возмножность отобрать все удаляемые строки через НайтиСтроки(), то делаю через неё.
В Противном случае - цикл в обратном направлении
13 User_Agronom
 
05.01.16
10:34
За год, наверное, уже 10я тема про удаление строк из ТЗ.

Чаще бывает только про очистку ТЗ.

Сбивается ли выборка ?
14 tank68
 
05.01.16
10:43
(10) Ну вообще если не делать через такие вещи платформа сама начинает оптимизировать запрос и не всегда оптимально поэтому временные таблицы в запросе в большинстве случаев гораздо быстрее работает чем перебирать данные в цикле

http://catalog.mista.ru/public/153851/
Книга знаний: Временные таблицы в 8.1
15 Garykom
 
гуру
05.01.16
10:43
(13) ну не умеют поиском пользоваться. поэтому и не знают что самый быстрый способ удаления строк, это создание новой ТЗ с переносом туда тех что не нужно удалять
16 tank68
 
05.01.16
10:47
(15) Все надеяться что в новой версии что то новое не описанное ранее
17 Живой Ископаемый
 
05.01.16
11:01
18 strange2007
 
05.01.16
11:47
Не понимаю в чём спор. Проверить то можно минут за несколько.
№1 (удаление без сортировок, пернебирая каждую строку).
10000 записей: 0,083600
100000 записей: 0,930294

№2 (сначала пометка удаляемых строк, потом сортировка и удаление):
10000 записей: 0,088318
100000 записей: 0,935507

База файловая, платформа 8.3.7
19 strange2007
 
05.01.16
11:51
+(18) Код выложить? Как его жёлтый плюсик обернуть?
20 Злопчинский
 
05.01.16
12:22
Восьмерочники открывают для себя клюшечные азы
Прикольненько
21 zak555
 
05.01.16
12:25
(20) ты 17 посмотри
22 strange2007
 
05.01.16
12:34
(21) Смотрел. У автора был конкретный вопрос, тема уже более 3-х часов висит, вот я и сделал замер минут за 15 для автора
23 zak555
 
05.01.16
12:39
(22)  делай замер на

ОбъектДокумента = Документ.ПолучитьОбъект();
КритерийОставленияСтрок = Новый Структура();
КритерийОставленияСтрок .Вставить("КакаяТаКолонка", КакоеТоЗначение)    
ОбъектДокумента.Товары.Загрузить(ОбъектДокумента.Товары.Загрузить(ОбъектДокумента.Товары.НайтиСтроки(КритерийОставленияСтрок)));
24 strange2007
 
05.01.16
12:50
(23) Сам делай)))))) Я для (0) сделал и выложил результаты замеров. Если надо что-то кому-то доказать или оптимизировать свой алгоритм, то пусть сам и замеряет скорость.
Эх, теоретики...
25 Nirvana
 
17.01.16
00:15
Это в небольших таблицах значений сортировка делается быстро.
А в огромных таблицах сортировка - чуть ли не самая медленная операция.
26 ifso
 
17.01.16
01:05
(25) главное не озвучивай, что при сортировке строки сдвигаются, а то мало ли что ^^