Re[4]: Дерево в SQL
От: DenisCh Россия  
Дата: 26.07.19 18:02
Оценка: 10 (1) +1 -1
Здравствуйте, Ops, Вы писали:

Ops> Можно сделать вспомогательную таблицу с transitive closure


Есть хорошее русское слово транзитивное замыкание . Оно было бы более уместно на RSDN
[url=https://github.com/abbat/avalon1.0.449[/url]
Re: Дерево в SQL
От: vmpire Россия  
Дата: 26.07.19 11:31
Оценка: 22 (1) +1
Здравствуйте, Pavel Dvorkin, Вы писали:


PD>А теперь вопрос — как их связать ? Необходимо, чтобы можно было 1) по tree.id получить корень его дерева и 2) имея treeitem.id любого элемента дерева, можно было получить заголовок дерева

PD>Пока вижу только одно решение — в каждом treeitem иметь treeId как FK на tree. Однако это значит, что у всех узлов этого дерева будет храниться этот treeId, что есть дублирование данных.
PD>Можно ли его избежать ?
Если это MSSQL — Используйте https://docs.microsoft.com/en-us/sql/t-sql/data-types/hierarchyid-data-type-method-reference?view=sql-server-2017
По нему за одну операцию получите корень дерева, а на него уже можно ссылаться из другой таблицы.
Re[5]: Дерево в SQL
От: wildwind Россия  
Дата: 06.08.19 11:22
Оценка: +2
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Предки мне вообще не нужны, потомки нужны в другом месте, с ними я разберусь, а сейчас мне нужно лишь по узлу получить заголовок дерева. Я не думаю, что вариант с просмотром восходящего пути к корню (хоть вручную, хоть средствами сервера, если они есть) является наилучшим решением. Просто в силу того, что нечего устраивать проход там, где можно обойтись без него.


Это классический компромисс между памятью (каждый узел хранит ссылку на дерево) и быстродействием (только корень хранит ссылку на дерево). Каждый разрешает его для себя сам. Либо избыточность данных, либо дополнительные вычисления.
Re: Дерево в SQL
От: ksg71 Германия  
Дата: 29.07.19 06:48
Оценка: 6 (1)
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Добрый день!


PD>Надо разместить в SQL дерево произвольной арности.

PD>Понятно, таблица treeitem и в ней parentId как FK на ее же id
PD>Проблема же вот в чем. У дерева должен быть заголовок, содержащий данные, относящиеся к дереву в целом, а не к элементам. Хорошо, еще таблица tree
PD>А теперь вопрос — как их связать ? Необходимо, чтобы можно было 1) по tree.id получить корень его дерева и 2) имея treeitem.id любого элемента дерева, можно было получить заголовок дерева

PD>Пока вижу только одно решение — в каждом treeitem иметь treeId как FK на tree. Однако это значит, что у всех узлов этого дерева будет храниться этот treeId, что есть дублирование данных.

PD>Можно ли его избежать ?

видел как то денормализованный вариант

NodeId AncestorId Distance

то есть узел связан со всеми предками,
и можно выбирать потомков/предков (и собственно корень) без рекурсии
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Отредактировано 29.07.2019 6:50 ksg71 . Предыдущая версия .
Re[6]: Дерево в SQL
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.07.19 08:57
Оценка: 1 (1)
Здравствуйте, Ops, Вы писали:
Ops>Это дословный перевод, который ничего не значит. Даже статья в вики какая-то хрень, в отличие от английской. А уж искать информацию по этому словосочетанию — смысла вообще нет.
А вы всё же попробуйте. Например, на этом сайте.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Дерево в SQL
От: Dym On Россия  
Дата: 06.08.19 10:48
Оценка: +1
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Пока вижу только одно решение — в каждом treeitem иметь treeId как FK на tree. Однако это значит, что у всех узлов этого дерева будет храниться этот treeId, что есть дублирование данных.

PD>Можно ли его избежать ?
А зачем избегать? Надо делать так, чтобы потом было удобно работать.
Счастье — это Glück!
Дерево в SQL
От: Pavel Dvorkin Россия  
Дата: 26.07.19 10:57
Оценка:
Добрый день!

Надо разместить в SQL дерево произвольной арности.
Понятно, таблица treeitem и в ней parentId как FK на ее же id
Проблема же вот в чем. У дерева должен быть заголовок, содержащий данные, относящиеся к дереву в целом, а не к элементам. Хорошо, еще таблица tree
А теперь вопрос — как их связать ? Необходимо, чтобы можно было 1) по tree.id получить корень его дерева и 2) имея treeitem.id любого элемента дерева, можно было получить заголовок дерева

Пока вижу только одно решение — в каждом treeitem иметь treeId как FK на tree. Однако это значит, что у всех узлов этого дерева будет храниться этот treeId, что есть дублирование данных.
Можно ли его избежать ?
With best regards
Pavel Dvorkin
Re: Дерево в SQL
От: GarryIV  
Дата: 26.07.19 11:00
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Пока вижу только одно решение — в каждом treeitem иметь treeId как FK на tree. Однако это значит, что у всех узлов этого дерева будет храниться этот treeId, что есть дублирование данных.

PD>Можно ли его избежать ?

Еще можно принудительно в каждом дереве держать root treeItem и ссылаться на нее из tree.

Но я бы скорее выбрал твое решение
WBR, Igor Evgrafov
Отредактировано 26.07.2019 11:02 GarryIV . Предыдущая версия .
Re: Дерево в SQL
От: Mihas  
Дата: 26.07.19 11:06
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Пока вижу только одно решение — в каждом treeitem иметь treeId как FK на tree.

А почему не наоборот? Запись из tree ссылается с помощью FK на коренной элемент в treeitem.
Сколько записей в tree, столько и деревьев в базе. Просто же.

PD>Понятно, таблица treeitem и в ней parentId как FK на ее же id

Такая структура позволяет закольцеваться. Имей в виду и закладывай проверки сразу.
Re[2]: Дерево в SQL
От: Pavel Dvorkin Россия  
Дата: 26.07.19 11:18
Оценка:
Здравствуйте, Mihas, Вы писали:

M>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>Пока вижу только одно решение — в каждом treeitem иметь treeId как FK на tree.

M>А почему не наоборот? Запись из tree ссылается с помощью FK на коренной элемент в treeitem.

А как тогда по любому treeitem.id (не корню) получить его tree ? Устроить восходящий подъем по parentId ?

M>Такая структура позволяет закольцеваться. Имей в виду и закладывай проверки сразу.


Понятно, что позволяет, но не грозит — такого просто не будет.
With best regards
Pavel Dvorkin
Re[3]: Дерево в SQL
От: Mihas  
Дата: 26.07.19 11:30
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>А как тогда по любому treeitem.id (не корню) получить его tree ? Устроить восходящий подъем по parentId ?

Если скорость не критична, то да. Я бы, кончено, пытался делать это средствами sql, чтобы не тащить вычисление подъема на клиента. Хранимку бы замастрякал или функцию.
Если скорость критична, то я тоже не вижу способов без дублирования. Альтернативой treeitem.treeId я вижу treeitem.treeItemRootId
Re[2]: Дерево в SQL
От: Pavel Dvorkin Россия  
Дата: 26.07.19 12:52
Оценка:
Здравствуйте, vmpire, Вы писали:

V>Если это MSSQL — Используйте https://docs.microsoft.com/en-us/sql/t-sql/data-types/hierarchyid-data-type-method-reference?view=sql-server-2017

V>По нему за одну операцию получите корень дерева, а на него уже можно ссылаться из другой таблицы.

Спасибо за информацию, но, увы, не MS SQL
With best regards
Pavel Dvorkin
Re: Дерево в SQL
От: Qulac Россия  
Дата: 26.07.19 14:27
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Добрый день!


PD>Надо разместить в SQL дерево произвольной арности.

PD>Понятно, таблица treeitem и в ней parentId как FK на ее же id
PD>Проблема же вот в чем. У дерева должен быть заголовок, содержащий данные, относящиеся к дереву в целом, а не к элементам. Хорошо, еще таблица tree
PD>А теперь вопрос — как их связать ? Необходимо, чтобы можно было 1) по tree.id получить корень его дерева и 2) имея treeitem.id любого элемента дерева, можно было получить заголовок дерева

PD>Пока вижу только одно решение — в каждом treeitem иметь treeId как FK на tree. Однако это значит, что у всех узлов этого дерева будет храниться этот treeId, что есть дублирование данных.

PD>Можно ли его избежать ?

Если разрешить клиенту обращаться к узлу только по его полному пути tree_id(title)/id_1/id_2 и т.д., то проблема вообще не возникает, усложняется только клиент.
Программа – это мысли спрессованные в код
Re[2]: Дерево в SQL
От: Pavel Dvorkin Россия  
Дата: 26.07.19 14:36
Оценка:
Здравствуйте, Qulac, Вы писали:

Q>Если разрешить клиенту обращаться к узлу только по его полному пути tree_id(title)/id_1/id_2 и т.д., то проблема вообще не возникает, усложняется только клиент.


Ну в таком случае достаточно передать tree_id и id_item. Этого хватит. Я-то хочу по id_item получить tree_id, и это все, что надо, а узлы выше id_item мне не нужны.
Но требовать от клиента передавать ID самого дерева и узла — это перенос избыточности на клиента. ID узла вообще-то неявно определяет ID самого дерева.
With best regards
Pavel Dvorkin
Re[3]: Дерево в SQL
От: Qulac Россия  
Дата: 26.07.19 14:46
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, Qulac, Вы писали:


Q>>Если разрешить клиенту обращаться к узлу только по его полному пути tree_id(title)/id_1/id_2 и т.д., то проблема вообще не возникает, усложняется только клиент.


PD>Ну в таком случае достаточно передать tree_id и id_item. Этого хватит. Я-то хочу по id_item получить tree_id, и это все, что надо, а узлы выше id_item мне не нужны.

PD>Но требовать от клиента передавать ID самого дерева и узла — это перенос избыточности на клиента.

ID узла вообще-то неявно определяет ID самого дерева.

Это если касаемо дерева в бд, если взять дерево как абстрактную структуру, то узел определяется путем к нему. Id у нас появляется как деталь реализации. Тут у нас либо клиент сложнее либо сервер.
Программа – это мысли спрессованные в код
Re[3]: Дерево в SQL
От: Ops Россия  
Дата: 26.07.19 15:22
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>А как тогда по любому treeitem.id (не корню) получить его tree ? Устроить восходящий подъем по parentId ?


Можно сделать view или вспомогательную таблицу с transitive closure, тогда то любому id одним запросом можно будет найти как всех его предков, так и потомков; опционально можно считать расстояние между ними, и, соответственно, выбирать лишь нужный уровень.

Однако мне такая структура только с id и parent_id (adjacent tree) не нравится, хотя она интуитивна и минимальна, но другие модели удобнее с практической точки зрения. Например в постгре есть хорошее расширение ltree, реализующее materialized path
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Отредактировано 26.07.2019 15:27 ути-пути . Предыдущая версия .
Re[5]: Дерево в SQL
От: Ops Россия  
Дата: 26.07.19 20:25
Оценка:
Здравствуйте, DenisCh, Вы писали:

DC>Есть хорошее русское слово транзитивное замыкание . Оно было бы более уместно на RSDN


Это дословный перевод, который ничего не значит. Даже статья в вики какая-то хрень, в отличие от английской. А уж искать информацию по этому словосочетанию — смысла вообще нет.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[4]: Дерево в SQL
От: Pavel Dvorkin Россия  
Дата: 27.07.19 01:38
Оценка:
Здравствуйте, Ops, Вы писали:

Ops>Можно сделать view или вспомогательную таблицу с transitive closure, тогда то любому id одним запросом можно будет найти как всех его предков, так и потомков; опционально можно считать расстояние между ними, и, соответственно, выбирать лишь нужный уровень.


Предки мне вообще не нужны, потомки нужны в другом месте, с ними я разберусь, а сейчас мне нужно лишь по узлу получить заголовок дерева. Я не думаю, что вариант с просмотром восходящего пути к корню (хоть вручную, хоть средствами сервера, если они есть) является наилучшим решением. Просто в силу того, что нечего устраивать проход там, где можно обойтись без него.
With best regards
Pavel Dvorkin
Re[4]: Дерево в SQL
От: Pavel Dvorkin Россия  
Дата: 27.07.19 01:46
Оценка:
Здравствуйте, Qulac, Вы писали:

Q>ID узла вообще-то неявно определяет ID самого дерева.


Ну да, вот только с восходящим проходом

Q>Это если касаемо дерева в бд, если взять дерево как абстрактную структуру, то узел определяется путем к нему. Id у нас появляется как деталь реализации. Тут у нас либо клиент сложнее либо сервер.


Если взять абстрактную структуру, то либо


class Tree { 
  private TreeItem root;
 // other tree header fields
}
class TreeItem {
 private TreeItem parent;
 private List<TreeItem> children;
 // TreeItem fields


В этом случае для получения по TreeItem его Tree восходящий проход по parent (aka parentId в БД)

Либо


class Tree { 
  private TreeItem root;
 // other tree header fields
}
class TreeItem {
 private TreeItem parent;
 private List<TreeItem> children;
 private Tree tree;
 // TreeItem fields


В этом случае по любому TreeItem его Tree находится за O(1), но все TreeItem одного дерева содержат одну и ту же ссылку tree (aka tree_id в БД)
With best regards
Pavel Dvorkin
Re[7]: Дерево в SQL
От: Ops Россия  
Дата: 29.07.19 09:12
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>А вы всё же попробуйте. Например, на этом сайте.


А я уже искал когда-то, и как раз там, где имел негативный опыт, пишу английские термины, чтобы другие не мучились. Русские термины — это хорошо, когда они устоявшиеся, и по ним достаточно информации, и я только за, если так станет, но пока имеем что имеем.
Только вот рьяные поборники русских терминов что-то не спешат хотя бы доработать статью в вики.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Отредактировано 29.07.2019 9:22 ути-пути . Предыдущая версия .
Re[8]: Дерево в SQL
От: Sinclair Россия https://github.com/evilguest/
Дата: 30.07.19 04:44
Оценка:
Здравствуйте, Ops, Вы писали:

Ops>А я уже искал когда-то, и как раз там, где имел негативный опыт, пишу английские термины, чтобы другие не мучились. Русские термины — это хорошо, когда они устоявшиеся, и по ним достаточно информации, и я только за, если так станет, но пока имеем что имеем.

Ops>Только вот рьяные поборники русских терминов что-то не спешат хотя бы доработать статью в вики.
Во-первых, я не вижу никаких проблем в вики-статье. Там и определение корректное, и примеры понятные.
Во-вторых, вы таки не пробовали искать на rsdn. Иначе бы нашли исчерпывающую дискуссию 11летней давности
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Дерево в SQL
От: Буравчик Россия  
Дата: 30.07.19 05:00
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Пока вижу только одно решение — в каждом treeitem иметь treeId как FK на tree. Однако это значит, что у всех узлов этого дерева будет храниться этот treeId, что есть дублирование данных.

PD>Можно ли его избежать ?

Чем дублирование данных мешает в твоем случае?
Best regards, Буравчик
Re: Дерево в SQL
От: AleksandrN Россия  
Дата: 30.07.19 11:57
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Пока вижу только одно решение — в каждом treeitem иметь treeId как FK на tree. Однако это значит, что у всех узлов этого дерева будет храниться этот treeId, что есть дублирование данных.

PD>Можно ли его избежать ?

Можно использовать первичный ключ из двух колонок — treeId, nodeId, например:
1,1
1,2
1,3
2,1
2,2

Либо часть разрядов в ID ключа использовать как ID дерева. Например, пусть PK имеет тип int(5), первые 2 разряда будет ID дерева, остальные — ID узла в дереве, т.е.:01
01001
01002
01003
02001
02002

Подобный подход я видел в БД КЛАДР.

Но такие подходы имеют минусы — вместо sequence придётся изобретать свой велосипед, работающий при множественных подключениях к БД, а это сильно усложнит логику твоей системы, увеличит сроки разработки и усложнит поддержку.

Поэтому, думаю, что бы узнать вершину дереву по его листу, лучше будет либо идти по дереву до вершины, либо хранить ID дерева в записи узла. Выбрать приоритет — скорость или отсутствие дублирования информации. Можно хранить вершину дерева не в узле, а в отдельной таблице с колонками treeID, nodeID, но это тоже дублирование информации.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.