Имя: Пароль:
1C
1С v8
Помогите составить рекурсивную функцию
0 hatsher
 
09.08.12
14:11
документ может вводиться на основании самого себя(такого же объекта МД).
Требуется по документу найти все документы, введенные на его основании + все документы, введенные на основании этих+ и тд
1 izekia
 
09.08.12
14:12
зачем рекурсию?
2 hatsher
 
09.08.12
14:13
а как по-другому? я не могу в запросе соединять бесконечное число таблиц..
3 izekia
 
09.08.12
14:13
а рекурсию ты в запросе можешь?
4 Wobland
 
09.08.12
14:14
этот глист страдал глистами, что мучались глистами сами
5 hatsher
 
09.08.12
14:14
(3) я могу составить рекурсивную функцию, которая будет использовать запрос.. но может можно как-то проще
6 Маратыч
 
09.08.12
14:15
(5) А как еще проще? Все верно, функция с запросом.
7 izekia
 
09.08.12
14:15
(5) запрос в рекурсии - это еще тот быдлокод
8 izekia
 
09.08.12
14:16
хотя здесь без разницы, но рекурсия точно не нужна
9 Alex S D
 
09.08.12
14:17
а типовой отчет по структуре подчиненности не прет?
10 Маратыч
 
09.08.12
14:17
(7) Ну через Док.ДокОснование без запроса. Какая разница? Быдлокод - это запрос в цикле, когда без цикла можно обойтись. А в рекурсии вполне уместно.
11 hatsher
 
09.08.12
14:17
(8) какой алгоритм примерно?
12 Маратыч
 
09.08.12
14:17
(8) Дык если длина цепочки неизвестна, без рекурсии как?
13 Mort
 
09.08.12
14:21
У хрусталевой есть пример построения в СКД своей иерархии. Не гарантирую что взлетит, не приходилось на практике как-то...
14 izekia
 
09.08.12
14:23
тест запроса упростил:
запрос = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Документ.МойДокумент ГДЕ Основание = &Основание");
результат = Новый Массив;
результат.Добавить(ИсходныйДокумент);
счетчик = 0;
Пока результат.Количество() > счетчик Цикл
  запрос.УстановитьПараметр("Основание", результат[счетчик]);
  выборка = запрос.Выполнить().Выбрать();
  Пока выборка.Следующий() Цикл
      результат.Добавить(выборка.Ссылка);
  КонецЦикла;
  счетчик = счетчик + 1;
КонецЦикла;
15 izekia
 
09.08.12
14:24
сорри за (7) в данном случае в рекурсии запрос - это не быдлокод, просто изначально неправильно представил себе структуру
16 hatsher
 
09.08.12
14:26
спасибо
17 izekia
 
09.08.12
14:26
в данном случае рекурсия - это зло, здесь мы добавляем всего одну переменную и сразу же создаем необходимый список документов и его же и обходим
18 Mort
 
09.08.12
14:26
+(13) Собсна не вижу причин, чтобы не взлетело.
19 hatsher
 
09.08.12
14:26
+ а можно усложнить задачу:)
20 Ненавижу 1С
 
гуру
09.08.12
14:26
(13) что вы возитесь со своей СКД как панацеей
СКД выполняется не в СУБД, а на сервере приложений, также может и обычный код, только СКД неуправляем внутри себя, ты просто что-то получаешь, но не знаешь как оно получено, оптимальностью управлять нельзя
21 izekia
 
09.08.12
14:27
(18) зачем усложнять?
22 izekia
 
09.08.12
14:27
(19) давай
23 hatsher
 
09.08.12
14:29
(21) исходная задача прост немного сложнее:

докМД1 вводится только на основании себя.
ДокМД2 вводится только на основании ДокаМД1

требуется найти найти все ДокМД2, у которых в основании по иерархии имеется ИсходныйДокумент
24 Mort
 
09.08.12
14:29
(20) Гм. На СКД это делается быстро. Только звучит страшно. Конечно можно и кодом, но это точно не будет запрос в цикле :)
25 Mort
 
09.08.12
14:29
+(24) быстро в смысле не оптимально, а время потраченное на разработку.
26 Mort
 
09.08.12
14:31
+ И не думаю что одинэсный транслятор в силах обогнать платформенные функции СКД.
27 hatsher
 
09.08.12
14:31
+ впронципе можно получить массив по 14 и найти все докМД2 по нахождению докОснование в этом массиве..
28 izekia
 
09.08.12
14:34
запрос = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Документ.МойДокумент ГДЕ Основание = &Основание");
основания = Новый СписокЗначений;
основания.Добавить(ИсходныйДокумент);
счетчик = 0;
Пока основания.Количество() > счетчик Цикл
  запрос.УстановитьПараметр("Основание", основания[счетчик].Значение);
  выборка = запрос.Выполнить().Выбрать();
  Пока выборка.Следующий() Цикл
      основания.Добавить(выборка.Ссылка);
  КонецЦикла;
  счетчик = счетчик + 1;
КонецЦикла;
запрос = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Документ.МойДокумент2 ГДЕ Основание В &Основания"
запрос.УстановитьПараметр("Основания", основания);
29 izekia
 
09.08.12
14:35
(26) хочешь потестить?)
30 izekia
 
09.08.12
14:35
(24) пример дай? я просто этот код написал не открывая 1С, это про скорость разработки
31 hatsher
 
09.08.12
14:36
(28) Спасибо!
32 Classic
 
09.08.12
14:36
(28)
Не отработан вариант при котором два документа - основания друг-друга
33 hatsher
 
09.08.12
14:37
(32) это врядли:) пользователю недоступно менять основание документа
34 Mort
 
09.08.12
14:37
(29) Как нибудь попробую.
(28) Этот код можно значительно оптимизировать, посылая запрос не на каждый документ, а на полученный ряд доков по основанию. Таким образом количество запросов будет равно количеству вложений, что не так уж много.
35 Classic
 
09.08.12
14:37
(33)
Все равно не аккуратненько :)
Хотя хороший пример как обойтись без рекурсии
36 izekia
 
09.08.12
14:38
(34) да, согласен
37 izekia
 
09.08.12
14:39
(35) циклические ссылки вряд ли допустимы чисто логически, можно проверять на вхождение
38 izekia
 
09.08.12
14:39
сейчас добавлю (32) и (34)
39 Ненавижу 1С
 
гуру
09.08.12
14:45
(24) то есть ты утверждаешь, что СКД построит эту иерархию без запроса в цикле?
40 izekia
 
09.08.12
14:50
запрос = Новый Запрос("ВЫБРАТЬ МД.Ссылка ИЗ Документ.МойДокумент КАК МД ГДЕ МД.Основание В &Основания");
основания = Новый Массив;
основания.Добавить(ИсходныйДокумент);
основанияДляЗапроса = Новый СписокЗначений;
основанияДляЗапроса.Добавить(ИсходныйДокумент);
Пока Истина Цикл
  запрос.УстановитьПараметр("Основание", основанияДляЗапроса);
  выборка = запрос.Выполнить().Выбрать();
  основанияДляЗапроса.Очистить();
  Пока выборка.Следующий() Цикл
      Если основания.Найти(выборка.Ссылка) = Неопределено Тогда
          основания.Добавить(выборка.Ссылка);
          основанияДляЗапроса.Добавить(выборка.Ссылка);
      КонецЕсли;
  КонецЦикла;
  Если основанияДляЗапроса.Количество() = 0 Тогда
      Прервать;
  КонецЕсли;
КонецЦикла;
запрос = Новый Запрос("ВЫБРАТЬ МД2.Ссылка ИЗ Документ.МойДокумент2 КАК МД2 ГДЕ МД2.Основание В &Основания"
основанияДляЗапроса.Загрузить(основания);
запрос.УстановитьПараметр("Основания", основания);
41 Mort
 
09.08.12
14:51
(39) Ну зуб бы не поставил (уже мало осталось) но по описанию сего чуда в хрусталевой, СКД строит подобную иерархию также как и для простых иерархических справочников. Отсюда предположение.
42 Mort
 
09.08.12
14:51
*так же
43 hatsher
 
09.08.12
14:53
надо бы добавить к БЗ
44 izekia
 
09.08.12
14:54
кстати, более забавная идея появилась)
сейчас попробую написать
45 Ненавижу 1С
 
гуру
09.08.12
15:00
(41) открою секрет, простую иерархию она тоже строит в цикле
46 izekia
 
09.08.12
15:04
+ (44) не, нет возможности дополнять временные таблицы, а так бы можно было красиво сделать