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
}
}
Категорические части на этом предмете были записаны Joe Celko, и он работал много их в книгу, названную Деревьями Joe Celko и Иерархиями в SQL для Присяжных острословов.
Он одобряет технику, названную ориентированными графами. Введение в его работу над этим предметом может быть найдено здесь
Мне нравится Измененный Алгоритм Обхода дерева Перед порядком. Эта техника делает очень легким запросить дерево.
, Но вот список ссылок о теме, которая я скопировал с Платформы Зенда (PHP) веб-страницу участников (отправленный там Отправленным Laurent Melmoux 05 июня 2007 15:52).
Многие ссылки являются агностиком языка:
существует 2 основных представления и алгоритмы для представления иерархических структур с базами данных:
списка смежности, Это хорошо объяснено здесь:
Вот являются еще некоторыми ссылками, которые я собрал:
модель
вложенный установила
классы Graphes
:
Вложенная груша ADOdb
Модели посещения Adodb
Дерева DB Наборов:: использование DB_NestedSetГРУША:: Дерево
nstrees
Что лучший способ состоит в том, чтобы представить 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.
Проблема, поддержание таблицы предка довольно трудно - лучше всего сделанный с хранимой процедурой.
Я должен не согласиться с 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;
К вашему сведению: SQL Server 2008 представляет новое тип данных HierarchyID для этого вида ситуации. Дает Вам контроль, где в "дереве" Ваша строка находится, горизонтально а также вертикально.
Oracle: ВЫБРАТЬ... ЗАПУСТИТЕ С... ПОДКЛЮЧЕНИЕ
Oracle имеет расширение для ВЫБОРА, который позволяет легкое основанное на дереве извлечение. Возможно, SQL Server имеет некоторое подобное расширение?
Этот запрос пересечет таблицу, где вложенные отношения хранятся в родитель и ребенок столбцы.
select * from my_table
start with parent = :TOP
connect by prior child = parent;
Я предпочитаю соединение методов, используемых Josh и Mark Harrison:
Две таблицы, один с данными Человека и другого с hierarchichal информацией (person_id, parent_id [mother_id]), если PK этой таблицы является person_id, у Вас есть простое дерево только с одним родителем узлом (который имеет смысл в этом случае, но не в других случаях как учет учетных записей)
, Эта hiarchy таблица может быть транссведущей рекурсивными процедурами или если Ваша поддержка БД это предложениями как ВЫБОР... ПРЕДШЕСТВУЮЩИМ (Oracle).
Другая возможность состоит в том, если Вы знаете макс. глубоко данных иерархии, Вы хотите поддержать, использование единственная таблица с рядом столбцов на уровень иерархии
У нас была та же проблема, когда мы реализовали древовидный компонент для [fleXive] и использовали вложенный подход модели дерева набора, упомянутый tharkun от документы MySQL .
В дополнение к вещам скорости (существенно) мы использовали , распространяется подход, который просто означает, что мы использовали максимум значение Long для высокоуровневых границ права, которое позволяет нам вставлять и перемещать узлы, не повторно вычисляя все левые и правые значения. Значения для левого и правого вычисляются путем деления диапазона для узла 3 использованием und внутренний треть как границы для нового узла.
пример кода Java А виден здесь .
При использовании SQL Server 2005 тогда , эта ссылка объясняет, как получить иерархические данные.
Общие Выражения Таблицы (CTEs) могут быть Вашими друзьями, как только Вы получаете удобное использование их.