SQL - Как сохранить и переместиться по иерархиям?

public class Test {

    public class A {}

    public class B extends A {}

    public class C extends B {}

    public void testCoVariance(List<? extends B> myBlist) {
        B b = new B();
        C c = new C();
        myBlist.add(b); // does not compile
        myBlist.add(c); // does not compile
        A a = myBlist.get(0); 
    }

    public void testContraVariance(List<? super B> myBlist) {
        B b = new B();
        C c = new C();
        myBlist.add(b);
        myBlist.add(c);
        A a = myBlist.get(0); // does not compile
    }
}
46
задан Mark Harrison 30 September 2016 в 04:37
поделиться

9 ответов

Категорические части на этом предмете были записаны Joe Celko, и он работал много их в книгу, названную Деревьями Joe Celko и Иерархиями в SQL для Присяжных острословов.

Он одобряет технику, названную ориентированными графами. Введение в его работу над этим предметом может быть найдено здесь

14
ответ дан The DIMM Reaper 26 November 2019 в 20:32
поделиться

Мне нравится Измененный Алгоритм Обхода дерева Перед порядком. Эта техника делает очень легким запросить дерево.

, Но вот список ссылок о теме, которая я скопировал с Платформы Зенда (PHP) веб-страницу участников (отправленный там Отправленным Laurent Melmoux 05 июня 2007 15:52).

Многие ссылки являются агностиком языка:

существует 2 основных представления и алгоритмы для представления иерархических структур с базами данных:

  • вложенный набор, также известный как измененный алгоритм обхода дерева перед порядком
  • модель

списка смежности, Это хорошо объяснено здесь:

Вот являются еще некоторыми ссылками, которые я собрал:

модель

вложенный установила

классы Graphes

:

Вложенная груша ADOdb

Модели посещения Adodb

Дерева DB Наборов:: использование DB_NestedSet

ГРУША:: Дерево

nstrees

31
ответ дан Paccc 26 November 2019 в 20:32
поделиться

Что лучший способ состоит в том, чтобы представить hierachy в базе данных SQL? Универсальная, портативная техника?

Позволяют нам предположить, что hierachy главным образом читается, но не абсолютно статичен. Скажем, это - родословная.

Вот то, как не сделать это:

create table person (
person_id integer autoincrement primary key,
name      varchar(255) not null,
dob       date,
mother    integer,
father    integer
);

И вставка данных как это:

person_id   name      dob       mother father  
1           Pops      1900/1/1   null   null  
2           Grandma   1903/2/4   null   null  
3           Dad       1925/4/2   2      1  
4           Uncle Kev 1927/3/3   2      1
5           Cuz Dave  1953/7/8   null   4
6           Billy     1954/8/1   null   3

Вместо этого разделяет Ваши узлы и Ваши отношения в две таблицы.

create table person (
person_id integer autoincrement primary key,
name      varchar(255) not null,
dob       date
);

create table ancestor (
ancestor_id   integer,
descendant_id integer,
distance      integer
);

Данные создаются как это:

person_id   name      dob       
1           Pops      1900/1/1  
2           Grandma   1903/2/4   
3           Dad       1925/4/2   
4           Uncle Kev 1927/3/3
5           Cuz Dave  1953/7/8   
6           Billy     1954/8/1   

ancestor_id  descendant_id  distance
1            1              0
2            2              0
3            3              0
4            4              0
5            5              0
6            6              0
1            3              1
2            3              1
1            4              1
2            4              1
1            5              2
2            5              2
4            5              1
1            6              2
2            6              2
3            6              1

можно теперь выполнить запросы arbitary, которые не включают присоединение к таблице назад на себе, который произошел бы, если у Вас есть heirachy отношения в той же строке как узел.

, у Кого есть бабушка и дедушка?

select * from person where person_id in 
    (select descendant_id from ancestor where distance=2);

Все Ваши потомки:

select * from person where person_id in 
    (select descendant_id from ancestor 
    where ancestor_id=1 and distance>0);

, Кто дяди?

select decendant_id uncle from ancestor 
    where distance=1 and ancestor_id in 
    (select ancestor_id from ancestor 
        where distance=2 and not exists
        (select ancestor_id from ancestor 
        where distance=1 and ancestor_id=uncle)
    )

Вы избегаете всех проблем соединения таблицы к себе через подзапросы, общее ограничение является 16 subsuqeries.

Проблема, поддержание таблицы предка довольно трудно - лучше всего сделанный с хранимой процедурой.

10
ответ дан Josh 26 November 2019 в 20:32
поделиться

Я должен не согласиться с Josh. Что происходит, если Вы используете огромную иерархическую структуру как организация компании. Люди могут присоединиться/оставить к компании, изменить линии оповещения и т.д... Поддержание "расстояния" было бы большой проблемой, и необходимо будет поддержать две таблицы данных.

Этот запрос (SQL Server 2005 и выше) позволил бы Вам видеть полную строку любого человека И вычисляет их место в иерархии, и это только требует единственной таблицы информации о пользователе. Это может быть изменено для нахождения любых дочерних отношений.

--Create table of dummy data
create table #person (
personID integer IDENTITY(1,1) NOT NULL,
name      varchar(255) not null,
dob       date,
father    integer
);

INSERT INTO #person(name,dob,father)Values('Pops','1900/1/1',NULL);  
INSERT INTO #person(name,dob,father)Values('Grandma','1903/2/4',null);
INSERT INTO #person(name,dob,father)Values('Dad','1925/4/2',1);
INSERT INTO #person(name,dob,father)Values('Uncle Kev','1927/3/3',1);
INSERT INTO #person(name,dob,father)Values('Cuz Dave','1953/7/8',4);
INSERT INTO #person(name,dob,father)Values('Billy','1954/8/1',3);

DECLARE @OldestPerson INT; 
SET @OldestPerson = 1; -- Set this value to the ID of the oldest person in the family

WITH PersonHierarchy (personID,Name,dob,father, HierarchyLevel) AS
(
   SELECT
      personID
      ,Name
      ,dob
      ,father,
      1 as HierarchyLevel
   FROM #person
   WHERE personID = @OldestPerson

   UNION ALL

   SELECT
    e.personID,
      e.Name,
      e.dob,
      e.father,
      eh.HierarchyLevel + 1 AS HierarchyLevel
   FROM #person e
      INNER JOIN PersonHierarchy eh ON
         e.father = eh.personID
)

SELECT *
FROM PersonHierarchy
ORDER BY HierarchyLevel, father;

DROP TABLE #person;
9
ответ дан NakedBrunch 26 November 2019 в 20:32
поделиться

К вашему сведению: SQL Server 2008 представляет новое тип данных HierarchyID для этого вида ситуации. Дает Вам контроль, где в "дереве" Ваша строка находится, горизонтально а также вертикально.

4
ответ дан Matt Hamilton 26 November 2019 в 20:32
поделиться

Oracle: ВЫБРАТЬ... ЗАПУСТИТЕ С... ПОДКЛЮЧЕНИЕ

Oracle имеет расширение для ВЫБОРА, который позволяет легкое основанное на дереве извлечение. Возможно, SQL Server имеет некоторое подобное расширение?

Этот запрос пересечет таблицу, где вложенные отношения хранятся в родитель и ребенок столбцы.

select * from my_table
    start with parent = :TOP
    connect by prior child = parent;

http://www.adp-gmbh.ch/ora/sql/connect_by.html

3
ответ дан Mark Harrison 26 November 2019 в 20:32
поделиться

Я предпочитаю соединение методов, используемых Josh и Mark Harrison:

Две таблицы, один с данными Человека и другого с hierarchichal информацией (person_id, parent_id [mother_id]), если PK этой таблицы является person_id, у Вас есть простое дерево только с одним родителем узлом (который имеет смысл в этом случае, но не в других случаях как учет учетных записей)

, Эта hiarchy таблица может быть транссведущей рекурсивными процедурами или если Ваша поддержка БД это предложениями как ВЫБОР... ПРЕДШЕСТВУЮЩИМ (Oracle).

Другая возможность состоит в том, если Вы знаете макс. глубоко данных иерархии, Вы хотите поддержать, использование единственная таблица с рядом столбцов на уровень иерархии

2
ответ дан Telcontar 26 November 2019 в 20:32
поделиться

У нас была та же проблема, когда мы реализовали древовидный компонент для [fleXive] и использовали вложенный подход модели дерева набора, упомянутый tharkun от документы MySQL .

В дополнение к вещам скорости (существенно) мы использовали , распространяется подход, который просто означает, что мы использовали максимум значение Long для высокоуровневых границ права, которое позволяет нам вставлять и перемещать узлы, не повторно вычисляя все левые и правые значения. Значения для левого и правого вычисляются путем деления диапазона для узла 3 использованием und внутренний треть как границы для нового узла.

пример кода Java А виден здесь .

1
ответ дан Paŭlo Ebermann 26 November 2019 в 20:32
поделиться

При использовании SQL Server 2005 тогда , эта ссылка объясняет, как получить иерархические данные.

Общие Выражения Таблицы (CTEs) могут быть Вашими друзьями, как только Вы получаете удобное использование их.

0
ответ дан NakedBrunch 26 November 2019 в 20:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: