Имя: Пароль:
1C
1C 7.7
v7: Выбрать запросом элементы справочника в группе, когда справочник большой-?
,
0 MWWRuza
 
гуру
18.05.18
22:33
Добрый день!
Что-то я затупил совсем...
База DBF. Скуеля нет и не будет, не реально...
Вот такой простейший код:

Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|Номенклатура = Справочник.Номенклатура.ТекущийЭлемент;
|Группировка Номенклатура;
|Условие(Номенклатура в Группа);
|"//}}ЗАПРОС
;

Ничего нового, давно и успешно работает... Но, тут столкнулся с базой, в которой справочник номенклатуры имеет около 44000 элементов. Ну и что, разве это так много? Объем файла dbf справочника всего около 12 мегабайт, индекс примерно такой-же. Ни о чем, в принципе... До предельных 2-х гигов, еще ср**ь и ср**ь... Но, почему-то запрос задумывается надолго, и в конце концов, 1С падает с ошибкой... В диспетчере задач наблюдается рост занятой памяти, свыше гига... Падает где-то на полутора. Компьютер, Core I-5, с 4 гигами, правда, система 32 бита. Пробовал на других компах, результат примерно такой-же... Это что, такая непосильная задача для старушки-семерки? Не может быть... Может у меня где-то "косяк"? Переходить на SQL, не вариант... Использовать прямые запросы... Ну, можно конечно, но что-то не хочется - вроде не та задача...
Что можно еще придумать? Перебирать справочник в цикле? Так работает, все элементы перебирает. Но, тогда сложно отобрать по родителю, структура вложенности групп не известна, и в разных случаях может меняться от 1 до четырех... Запросом и условием в нем "Условие(Номенклатура в Группа)" это намного проще делается...
1 NSSerg
 
18.05.18
22:48
(0) Ничего не понял.
спр.ИспользоватьРодителя() отработает ровно так-же как и твой запрос. Со всеми уровнями вложенности.

//*******************************************
Процедура Сформировать()
      спр=создатьобъект("Справочник.Номенклатура");
      спр.использоватьродителя(Группа);
      спр.Выбратьэлементы(1);              
      Пока спр.Получитьэлемент()=1 цикл
      
      конеццикла;    
КонецПроцедуры
2 MWWRuza
 
гуру
18.05.18
22:55
Да? Не знал, думал только непосредственно родителя выбирает... Век живи, век учись... Спасибо!

И все-таки, почему запрос падает?
3 NSSerg
 
18.05.18
22:59
(2) Сделай "тестирование и исправление" на копии.
4 Злопчинский
 
18.05.18
23:09
(2) зацикленная ссылка где-то.
5 MWWRuza
 
гуру
18.05.18
23:19
Запустил тестирование, думал, база пустая, ща, пять минут и готово будет!
А нет, фиг там... Физ. целостность и реиндексацию пролетел моментом, а на логике застрял... Хотя, так подумать, какая там логика - база пустая, ни одного документа, только справочники - Номенклатура, Единицы, Цены, Контрагенты, ЮрЛица... Ну, таблица константы(история периодических реквизитов, учитывая, что база почти пустая, только справочника Цены)... О чем там можно так долго думать? Наверно правда зацикленная ссылка... ТиИ должно ее найти и исправить?
6 Злопчинский
 
18.05.18
23:33
(5) "ТиИ должно ее найти и исправить?"
- а вот даже и не знаю... не факт
7 MWWRuza
 
гуру
18.05.18
23:51
Блинн.... Все еще думает... Странно, откуда там могла циклическая ссылка образоваться... Справочники загружены обработкой, из файла выгрузки на кассу... Ничего особенного. Правда, потом, еще перенесена иерархия из другой базы, восьмерошной, тоже обработками через текстовый файл. Может там чего накосячил? Хотя, чего там можно накосячить... Просто сначала установил родителя элементам, следующим проходом установил родителя группам, и так еще два раза. Понимаю, что криво, но, такая задача была - сначала загрузи просто, а потом оказалось что группы нужны. Писать чего-то универсальное некогда было, делал обработки под конкретную задачу...
8 MWWRuza
 
гуру
18.05.18
23:58
Проверить в цикле:

Если Спр.Родитель.Родитель = Спр.Родитель?
И потом вручную "починить" - ?
Или как лучше искать такую бяку?
9 NSSerg
 
19.05.18
00:12
(8) Поиск циклов в графе?
http://e-maxx.ru/algo/finding_cycle
10 NSSerg
 
19.05.18
00:24
1. Проверить что родителем каждого элемента (и группы)
является либо пустое значение либо группа справочника.
2. Проверить для групп что родителем не является он сам.
3. Проверить что родитель родителя не является он сам и т.д.


//*******************************************
Процедура Сформировать()
    сч=0;
    спр=создатьобъект("Справочник.Номенклатура");
    спр.выбратьэлементы(0);
    Пока спр.Получитьэлемент()=1 цикл
        сч=сч+1;
        состояние(сч);
        тек=спр.текущийэлемент();
        род=тек.родитель;
        уровень=тек.уровень();
        Пока пустоеЗначение(род)<>1 цикл
            если род.этогруппа()=0 Тогда
                сообщить("родитель не группа "+род.код+" "+тек.код);
                прервать;
            конецесли;
            если род=тек тогда
                сообщить("Цикл "+род.код+" "+тек.код);
                прервать;
            конецесли;
            если род.уровень()<>уровень-1 Тогда
                сообщить("Цикл по уровню "+род.код+" "+тек.код);
                прервать;
            конецесли;
            уровень=уровень-1;
            род=род.родитель;  
        Конеццикла;
    Конеццикла;    
    сообщить("обработка завершена");    
КонецПроцедуры
11 MWWRuza
 
гуру
19.05.18
00:34
(10)Ага... На 669 застрял. Сейчас выведу в состояние имена, что-бы посмотреть, на чем именно...
12 MWWRuza
 
гуру
19.05.18
01:47
Не отрабатывает эта обработка до конца, встает наглухо при первой же ошибке, и соответственно ничего не сообщает... Надо наверное через Попытку Исключение делать...

Сделал вот так, сил нет разбираться, спать хочу:
состояние("Эл " + сч + " " + СокрЛП(Спр.Код) + " " +СокрЛП(Спр.Наименование) + " " + СокрЛП(Спр.Родитель) + " " + СокрЛП(Спр.Родитель.Код) + " " + СокрЛП(Спр.Родитель.Родитель) + " " + СокрЛП(Спр.Родитель.Родитель.Код));

В общем, оказалось пять таких "кривых" групп...
Ну да ладно, по одной исправил...
Думал, по природной лени, не буду обработку писать, исправлю интерактивно... ЩАС!!! Эти группы не видны в справочнике, не понятно, в каких родительских группах их искать... Думал, отключу вывод списка по группам, и найду. Нашел, но программа глухо зависает, как только эта группа попадает в видимую часть списка... Плюнул, вывел коды этих групп, и такой обработкой:

Процедура ОчиститьРодителя()
    Спр = СоздатьОбъект("Справочник.Номенклатура");
    Если Спр.НайтиПоКоду(ИскКод) = 1 Тогда
        Спр.Родитель = "";
        Спр.Записать();
    КонецЕсли;    
КонецПроцедуры

вынес их в корень, по одной, вручную, благо их всего пять :-)

Все работает после этого отлично, и запрос, и ТиИ за пару минут прошло. А группы, вынесенные в корень, пусть потом клиенты интерактивно куда хотят переносят, я все равно не знаю, где они у них должны были быть...

Всем спасибо за помощь! На будущее буду внимательнее, это спешка, когда писал обработку переноса иерархии...