![]() |
![]() |
|
Таблица иерархии и проверка зацикленности | ☑ | ||||||
---|---|---|---|---|---|---|---|---|
0
Ненавижу 1С
гуру
27.07.11
✎
15:09
|
Есть таблица с двумя полями: ссылка и родитель. Ссылка в таблице уникальна и всегда заполнена. Родитель - это ссылка непосредственного родителя (он тоже обязательно есть в некоторой записи этой таблицы в поле Ссылка). Если родителя нет, то поля Родитель не заполнено (ммм... в терминах 1С "пустая ссылка") - это корневой элемент.
Требуется написать ОДИН запрос (можно пакетный) на языке запросов 1С, с помощью которого можно проверить нет ли в этой таблице иерархии зацикленности? То есть проверить на валидность данные. Взлетит? |
|||||||
1
Ник второй
27.07.11
✎
15:11
|
Давай свой вариант. Как можно судить о взлетах ?
|
|||||||
2
Ненавижу 1С
гуру
27.07.11
✎
15:12
|
(1) нужен запрос, если он есть, то взлетит, если есть хоть какое-то приемлимое обоснование, что нельзя - значит не взлетит
|
|||||||
3
Fragster
гуру
27.07.11
✎
15:13
|
это порочная структура, реально. правильная структура - ссылка, левое значение, правое значение, уровень. родитель опционален.
и дерево вида (1,6,0) (2,3,1)(4,5,1) |
|||||||
4
Ненавижу 1С
гуру
27.07.11
✎
15:14
|
(3) структура уже задана, порочная она или нет, другой вопрос
меня интересует можно проверить запросом на зацикленность или нет |
|||||||
5
Ник второй
27.07.11
✎
15:16
|
Имхо. нет.
|
|||||||
6
Jstunner
27.07.11
✎
15:16
|
невозможно утверждать о зацикленности не пройдя все точки. Циклов в запросах нет
Нет |
|||||||
7
Ник второй
27.07.11
✎
15:16
|
голос забыл
Нет |
|||||||
8
Fragster
гуру
27.07.11
✎
15:17
|
(4) может коррелированными подзапросами и можно как-то извратится. только это не стандартный T_SQL, да и хз, только 1 раз написал такой запрос, как раз для построения дерева (но там гарантированно не было циклов)
|
|||||||
9
Fragster
гуру
27.07.11
✎
15:17
|
ыц
Нет |
|||||||
10
Ник второй
27.07.11
✎
15:17
|
(6) Циклы в запросах есть , но не те.
|
|||||||
11
Axel2009
27.07.11
✎
15:31
|
(0) нужно выдать на экран или обработать результат?
|
|||||||
12
catena
27.07.11
✎
15:42
|
КОличество уровней неизвестно?
|
|||||||
13
Lama12
27.07.11
✎
15:44
|
Недавно тема обсасывалась, но без запросов.
Та дано оптимальное решение. Если на запрос переведешь, то получится. |
|||||||
14
Ненавижу 1С
гуру
27.07.11
✎
15:51
|
(11) нужно запросом дать данные, которые уже обработки не требуют (или требуют за фиксированное время)
|
|||||||
15
Mort
27.07.11
✎
15:52
|
И это можно доказать, оперируя порядком вычислений необходимого для решения данной задачи и порядком который может "предложить" один запрос.
|
|||||||
16
Mort
27.07.11
✎
15:53
|
+(15) Почему то не проголосовалось.
Нет |
|||||||
17
Юрий Лазаренко
27.07.11
✎
15:54
|
(0) Сам недавно бодался с подобной ботвой, в итоге остановился на рекурсии.
Нет |
|||||||
18
Axel2009
27.07.11
✎
15:57
|
(14) если тока вывести, можно скд попробовать, там есть рекурсии встроенные.. набор данных сам на себя зациклить..
|
|||||||
19
sikuda
27.07.11
✎
16:23
|
Реляционный подход требует получения данных за ограниченное количество внутренних запросов в системе. Если вы используете рекурсию типа TSQL оператор with, то количесто подзапросов растет как квардат от уровня вложенности. Если количество вложенности до 10, то этот костыль подходит. Но запихнуть его в 1С мне не удалось.
В общем случае создавайте кэш-РегистрСведений Родитель(любого уровня), Ссылка, УровеньВложенности. Записывайте его при любом изменении иерархии. С помощью этой структуры ваш запрос строиться легко. Нет |
|||||||
20
Ахиллес
27.07.11
✎
16:35
|
Что есть в данном случае "Зацикленность"? У Ссылки1 родитель равен Сылка2, а у Ссылка2 родитель равен Ссылка1?
|
|||||||
21
Axel2009
27.07.11
✎
16:38
|
(20) это была бы халява
|
|||||||
22
Ахиллес
27.07.11
✎
16:40
|
(21) Что тогда найти надо? Неоднократные ссылки? Ещё большая халява тогда. Что есть зацикленность?
|
|||||||
23
Axel2009
27.07.11
✎
16:41
|
(22)
ссылка1, ссылка2 ссылка2, ссылка3, ... ссылкаN, ссылка1 |
|||||||
24
Ахиллес
27.07.11
✎
16:45
|
Запрос1: Выбрать Элемент, Родитель, группировка по Элемент,Родитель, где Родитель не пустое значение.
Запрос2: Выбрать Элемент2, Родитель2, группировка по Элемент2,Родитель2, где Родитель2 не пустое значение. Внутреннее соединение по Элемент = Родитель2 З.Ы. Если х.ню сморозил - звиняйте :-) |
|||||||
25
Ахиллес
27.07.11
✎
16:59
|
Не это ересь я какую то написал. Необходимо ещё уровень элемента знать. И дополнительное условие по сравнению уровней, я так понимаю.
|
|||||||
26
Fragster
гуру
27.07.11
✎
17:01
|
(25) а какой уровень у зациклившихся элементов?
|
|||||||
27
Ахиллес
27.07.11
✎
17:05
|
(26) У родителя меньше чем у элемента?
|
|||||||
28
Ахиллес
27.07.11
✎
17:08
|
то есть больше. :-)
|
|||||||
29
Fragster
гуру
27.07.11
✎
17:26
|
(27) а кто из них родитель? там же как раз и прикол в неоднозначности уровня
|
|||||||
30
Ахиллес
27.07.11
✎
17:51
|
(29) Цитата из (0) Есть таблица с двумя полями: ссылка и родитель. Значит надо просто дополнить эту таблицу уровнем элемента и уровнем родителя
|
|||||||
31
Axel2009
27.07.11
✎
17:52
|
(30) а что это даст?
|
|||||||
32
Ахиллес
27.07.11
✎
17:54
|
(31)Если уровень родителя больше уровня элемента, то косяк.
Собственно при нормальном заполнении ситуация в (23) невозможна в принципе. Х.З. Как эту таблицу Ненавижу 1С заполняет и почему у него там какая то зацикленность образовалась. |
|||||||
33
Axel2009
27.07.11
✎
17:56
|
(32) когда дерево заполняет пользователь на глаз, то каждый пересчет может занимать "долгое" время наверна
|
|||||||
34
Ахиллес
27.07.11
✎
18:01
|
(33) Нифига не понял.
|
|||||||
35
Axel2009
27.07.11
✎
18:02
|
ну вот сидит пользователь, дается ему 2 колонки, ссылка, родитель. он заполняет ее сначала, а потом надо проверить, все ли он корректно ввел. если по каждому тыку проверять, пользователь будет сидеть по паре секунд и ждать когда же это произойдет..
|
|||||||
36
Живой Ископаемый
27.07.11
✎
18:04
|
2(35) зачем проверять после того как он наделал ошибок а не каждый раз как он вводит новую строку?
Или это специальный пользователь, обученный заполнять сначала только одну колонку, а потом только вторую во всей таблице сразу? |
|||||||
37
Живой Ископаемый
27.07.11
✎
18:05
|
"если по каждому тыку проверять" непонятно пчоему по паре секунд а не мгновенно
|
|||||||
38
Fragster
гуру
27.07.11
✎
18:06
|
(30) у первого элемента родителем второй, у второго - первый. у кого какой уровень?
|
|||||||
39
Ахиллес
27.07.11
✎
18:06
|
(35) В момент заполнения элемента и родителя пусть проверяются уровни элемента и уровень родителя. Если уровень родителя больше уровня эдемента, включается разрядник в сиденье стула на 1000 вольт. Я не могу придумать, как иначе образуется эта зацикленность?
|
|||||||
40
Ахиллес
27.07.11
✎
18:08
|
(38) Мы ведь о многоуровневом справочнике говорим? В таком случае Уровень это объективное свойство элемента. Не надо думать какой уровень, надо просто взять и посмотреть на него.
|
|||||||
41
Fragster
гуру
27.07.11
✎
18:09
|
(40) в (0) нет уровня, есть таблица с 2 колонками. требуется проверить возможность построения дерева.
|
|||||||
42
Живой Ископаемый
27.07.11
✎
18:10
|
2(40) нет, не обязательно... Автор может думать как организовать альтернативную иерархию... Ну например...
Есть справочник контрагентов - он заполняется как бог на душу положит бухгалтерии или например по Гегорафическому принципу... А на другом уровне эти контрагенты связаны между собой иерархией Агент-субагент |
|||||||
43
Ахиллес
27.07.11
✎
18:10
|
(41) В таблице есть ССЫЛКИ, а у ссылки есть метод Уровень()
|
|||||||
44
Живой Ископаемый
27.07.11
✎
18:12
|
по географическому принципу
1.ЦАО 1.1.МосковскаяОбласть 1.1.1 агент Вася 1.2. Калужская Область 1.2.1 агент Петя а альтернативная ирерхия выглядит так: 1. агент Вася из московской области 1.1. субагент Петя из Калужской области |
|||||||
45
Fragster
гуру
27.07.11
✎
18:13
|
(43) при чем тут? допустим, мы строим произвольную (альтернативную) иерархию, и у нас РС с 2 измерениями: Ссылка и Родитель.
|
|||||||
46
Ахиллес
27.07.11
✎
18:16
|
(44) Нарисуй зацикленное дерево к первой иерархии.
|
|||||||
47
Fragster
гуру
27.07.11
✎
18:17
|
*facepalm*
|
|||||||
48
Живой Ископаемый
27.07.11
✎
18:18
|
2(46) а ему и не нужно проверять зацикленность первой. Он хочет проверить зацикленность второй.
а выглядит это просто: Агент: СуперАгент 1. агент Вася из московской области | 1.1. субагент Петя из Калужской области 1.1. субагент Петя из Калужской области | 1. агент Вася из московской области |
|||||||
49
МихаилМ
27.07.11
✎
18:22
|
--------------------------
можно только если известно макс колво вложенности уровней но можно построить более эффективнуюю иерархию : в cсылке можно закодировать иерархию. и проверять её при создании элемента. тогда можно создать эффективный индекс. Нет |
|||||||
50
rs_trade
27.07.11
✎
18:24
|
(19) почему только до 10?
|
|||||||
51
Ахиллес
27.07.11
✎
18:33
|
Если таблица соответствует новой иерархии, то действует простое правило, кто первый встал, того и тапки. Мы же должны знать на какой уровень иерархии мы хотим поместить создаваемый элемент? Как только создаётся элемент в новой иерархии ему моментально присваивается уровень. Без этого условия новую иерархию вообще невозможно построить. А раз уж мы присвоили уровень, то мы можем сравнивать их для новой пары.
|
|||||||
52
Ахиллес
27.07.11
✎
18:43
|
Для случая (48)
Создаем 1. агент Вася из московской области и решаем, что он будет родителем всех агентов. (Должны же мы с чего то начать дерево? Поэтому получите Вася первый уровень и распишитесь) Далее мы создаём 1.1. субагент Петя из Калужской области и решаем, что вася должен стать его родителем. Да не вопрос. Вот тебе Петя второй уровень. Дальше мы вышли покурить, а кто то нам решил помочь. Заводит 1.1. субагент Петя из Калужской области и решает, что Петя должен стать родителем Васи. И тут же получает граблями по лбу, потому, что Вася уже был заведён ранее и уже имеет уровень 1 который меньше чем у предпологаемого родителя. |
|||||||
53
Живой Ископаемый
27.07.11
✎
18:45
|
2(52) все верно, как-то так...
|
|||||||
54
vmv
27.07.11
✎
18:50
|
уже давно создан алгоритм превращения тз в дерево по набору полей иерархии посредством запсроса с менеджером временных таблиц(ищем на инфостаре).
его, кто хотел, докрутил по корректной обработке всех полей таблицы. Заодно он покакзывает зацикленности или его(алгоритм) можно заставить это делать веласипед снова изобретаем |
|||||||
55
МихаилМ
27.07.11
✎
18:51
|
(54)
пожалуста ссылку дайте. |
|||||||
56
Ахиллес
27.07.11
✎
18:53
|
(54) На какой фабрике таких умных делают? Или алгоритм опиши или ссылку прямую дай. А на предъявы типа ищите на инфостарте/гугле/яндексе можно аналогичный посыл получить, куда Макар телят не гонял.
|
|||||||
57
vmv
27.07.11
✎
18:53
|
(52) "вольная" работа с группами - однин из больших минусов платформы 1С. Мне пришлось к ключевым справочникам: ОС, Контрагенты, Номенкратура, ФизЛица прикручивать подписчики ПередЗаписью, которые при создании пользователем нового элемента "кладут" его программно именно в тут группу, которая определена
|
|||||||
58
Ахиллес
27.07.11
✎
18:55
|
(57) Ты не зациклишь справочник в 1С.
|
|||||||
59
Живой Ископаемый
27.07.11
✎
18:58
|
2(58) даже если будет включена не иерархия групп, а иерархия групп и элементов? даже если после интерактивной записи потом программно для элемента-родителя назначу родителем элемент-потомок?
не проверял, просто спрашиваю. |
|||||||
60
vmv
27.07.11
✎
19:00
|
(58) не-а, В новом ПланВидов характеристик задаются правила иерархии для этих справочников согласно наборам реквизитов объекта.
Например если при вводе нового контрагента выбрали, что это юр.лицо, что форма собственности "ООО" и это, допустим поставшик, то он "падает" в свою иерархию и любая попытка перемешщения его из групы будет "натыкаться" на это правило расположения в иерахии, упорно записывая его в ту группу, что определена ПВХ. Если пользователь ничего не выбрал, то элемент падает в корень, а пользователь получает втык за лень и скопление незаполненных элементов. |
|||||||
61
Ахиллес
27.07.11
✎
19:01
|
(59) Ну интерактивно точно не получится. Я верю в то, что создатели 1С не конченые дауны, а програмно тоже не пробовал. Завтра попробую.
|
|||||||
62
Живой Ископаемый
27.07.11
✎
19:02
|
2(60) да, тоже способ.
|
|||||||
63
vmv
27.07.11
✎
19:12
|
(56) пример вызова и метод ниже, метод не совсем оптимален в смысле кода, но я ему "скармливаю" любые тз для получения иерархий и итогов по числовым полям, полезно, например, для работы с банками, группировать дата/банк/Валюта деревья и импортить потом куда хочь
// Инициализация массива колонок группировок и структуры с колонками пересчета. // В структуру колонок пересчета включаем все поля, но суммирование будет произведено только по числовым. мКолонкиГруппировок = Новый Массив; мКолонкиГруппировок.Добавить("Уровень"); СтруктураКолонокПересчета = Новый Структура; Для Каждого Колонка Из ТзСоставКлассификации.Колонки Цикл КолонкиИмя = Колонка.Имя; Если ЗначениеЗаполнено(мКолонкиГруппировок.Найти(КолонкиИмя)) ИЛИ КолонкиИмя = "НомерСтроки" Тогда Продолжить; КонецЕсли; СтруктураКолонокПересчета.Вставить(КолонкиИмя, "Сумма"); КонецЦикла; // Получение из таблицы значений дерева значений через метод менеджера внешних таблиц. ДеревоСоставаПорядкаИерархии = AddДеревья.ПолучитьДеревоПоТаблице(ТзСоставКлассификации, мКолонкиГруппировок, СтруктураКолонокПересчета, Истина, "Элементы"); // Функция получает дерево значений по таблице значений, достраивая иерархию // // Параметры: // 1.Источник - "ТаблицаЗначений" // 2.мКолонкиГруппировок - массив имен колонок по которой должна быть достроена несуществующая иерархия // 3.СтруктураКолонокПересчета - Структура - Структура с именами колонок требующих пересчета и функциями пересчета // Функция ПолучитьДеревоПоТаблице(Источник, мКолонкиГруппировок, СтруктураКолонокПересчета, СИерархией=Истина, ТипИзмеренияЗапроса="ИЕРАРХИЯ") Экспорт Перем мКолонкиВыборки; Если мКолонкиГруппировок.Количество() = 0 Тогда Возврат Новый ДеревоЗначений; КонецЕсли; мКолонкиВыборки = ОбщегоНазначения.СкопироватьУниверсальнуюКоллекцию(мКолонкиГруппировок); Для Каждого КолонкаПересчета Из СтруктураКолонокПересчета Цикл Если мКолонкиВыборки.Найти(КолонкаПересчета.Ключ) = Неопределено Тогда мКолонкиВыборки.Добавить(КолонкаПересчета.Ключ); КонецЕсли; КонецЦикла; //Если мКолонкиВыборки.Найти("НомерСтроки") = Неопределено Тогда // мКолонкиВыборки.Вставить(0, "НомерСтроки"); //КонецЕсли; // Получаем временную таблицу Запрос = Новый Запрос; МВТ = Новый МенеджерВременныхТаблиц; Запрос.МенеджерВременныхТаблиц = МВТ; ЗапросТекст = "ВЫБРАТЬ "; СЧ = 0; Для Каждого КолонкаИмя Из мКолонкиВыборки Цикл СЧ = СЧ + 1; ЗапросТекст = ЗапросТекст + Символы.ПС + "ТЗСостав."+ КолонкаИмя + " КАК "+ КолонкаИмя + ?(СЧ = мКолонкиВыборки.Количество(),"",","); КонецЦикла; ЗапросТекст = ЗапросТекст + Символы.ПС + "ПОМЕСТИТЬ ТЗВременная |ИЗ | &ТЗСостав КАК ТЗСостав"; Запрос.Текст = ЗапросТекст; Запрос.УстановитьПараметр("ТЗСостав", Источник); Запрос.Выполнить(); // Получаем Дерево запросом из временной таблицы Запрос = Новый Запрос; Запрос.МенеджерВременныхТаблиц = МВТ; ЗапросТекст = "ВЫБРАТЬ "; СЧ = 0; Для Каждого КолонкаИмя Из мКолонкиВыборки Цикл СЧ = СЧ + 1; ЗапросТекст = ЗапросТекст + Символы.ПС + "ТЗСостав."+ КолонкаИмя + " КАК "+ КолонкаИмя + ?(СЧ = мКолонкиВыборки.Количество(),"",","); КонецЦикла; ЗапросТекст = ЗапросТекст + Символы.ПС + " ИЗ | ТЗВременная КАК ТЗСостав |ИТОГИ"; // СчЧисловыхПолей = 0; Для Каждого КолонкаПересчета Из СтруктураКолонокПересчета Цикл ТипКлюча = Источник.Колонки[КолонкаПересчета.Ключ].ТипЗначения; ПустоеЗначение = ТипКлюча.ПривестиЗначение(); Если ТипЗнч(ПустоеЗначение) = Тип("Число") Тогда СчЧисловыхПолей = СчЧисловыхПолей + 1; КонецЕсли; КонецЦикла; // СЧ = 0; Для Каждого КолонкаПересчета Из СтруктураКолонокПересчета Цикл ТипКлюча = Источник.Колонки[КолонкаПересчета.Ключ].ТипЗначения; ПустоеЗначение = ТипКлюча.ПривестиЗначение(); Если ТипЗнч(ПустоеЗначение) <> Тип("Число") Тогда Продолжить; КонецЕсли; СЧ = СЧ + 1; ЗапросТекст = ЗапросТекст + Символы.ПС + КолонкаПересчета.Значение + " ("+ КолонкаПересчета.Ключ + ")" + ?(СЧ = СчЧисловыхПолей,"",","); КонецЦикла; СтрокаИтогиПо = ""; Для Каждого КолонкаИмя Из мКолонкиГруппировок Цикл СтрокаИтогиПо = ?(ПустаяСтрока(СтрокаИтогиПо), КолонкаИмя + " " + ТипИзмеренияЗапроса, СтрокаИтогиПо + ", " + КолонкаИмя + " " + ТипИзмеренияЗапроса); КонецЦикла; Если Не ПустаяСтрока(СтрокаИтогиПо) Тогда ЗапросТекст = ЗапросТекст + Символы.ПС + "ПО | " + СтрокаИтогиПо; КонецЕсли; Запрос.Текст = ЗапросТекст; Если СИерархией Тогда Дерево = Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией); Иначе Дерево = Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам); КонецЕсли; МВТ.Закрыть(); Возврат Дерево; КонецФункции |
|||||||
64
Живой Ископаемый
28.07.11
✎
08:39
|
2(58) Ну... интерактивно да - не выходит:
http://screencast.com/t/a73wZNvDsb6C |
|||||||
65
Живой Ископаемый
28.07.11
✎
08:51
|
Но вот такой запрос:
ВЫБРАТЬ 2 * 2 КАК Поле1, Подразделения.Ссылка, Подразделения1.Ссылка КАК Ссылка1 ИЗ Справочник.Подразделения КАК Подразделения, Справочник.Подразделения КАК Подразделения1 ГДЕ Подразделения.Ссылка = &Ссылка И Подразделения1.Ссылка = &Ссылка1 Где параметр Ссылка я задаю в элемент первого уровня, а Ссылка1 в его потомка третьего уровня, дает мне одну строку. к этой строке я применяю такой код: Первое = СтрокаРезультата.ССылка.ПолучитьОбъект(); Первое.ОбменДанными.Загрузка = Истина; Первое.Родитель = СтрокаРезультата.ССылка1; Первое.Записать(); прокатывает, и после этого если открыть форму списка справочника Подразделения - там нет ни элемента первого уровня и ни одного его потомка... Но если выполнить запрос к справочнику вцелом, то эти элементы видны. И можно даже открыть сам элемент.. Но вот по кнопке "Перейти в список" Толстый клиент подвисает - видимо зацикливается... :)) |
|||||||
66
Живой Ископаемый
28.07.11
✎
10:59
|
автор потерял интерес? :)
|
|||||||
67
Ненавижу 1С
гуру
28.07.11
✎
11:00
|
(66) автор понял, что задача неразрешима в постановке (0)
автор ошибался когда постил |
|||||||
68
Живой Ископаемый
28.07.11
✎
11:03
|
(67) ну тебя хоть фокус из (65) порадовал? :)
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |