Вернувшись, когда я работал в магазине Oracle, я принял CONNECT_BY как должное. Теперь я застрял в работе с SQL Server 2005 и имею некоторые неприятные иерархии объектов. В частности, у нас есть таблица самореференций, где все дочерние записи имеют столбец с родительским идентификатором. В настоящее время у нас есть представление, которое отображает детей на уровни в иерархии и неприятный запрос, который делает тяжелый подъем, чтобы связать родителей со своими детьми. Хотя этот метод работает, он далеко не изящный и пахнет пятнами. Мне просто интересно, как другие люди извлекают иерархические данные из SQL Server 2005.
Иерархические запросы в SQL Server 2005
Ответ 1
Это создает типичную иерархическую таблицу и использует CTE для выбора структуры иерархии и создания пути для каждого элемента.
CREATE TABLE tblHierarchy (ID int, ParentID int NULL, Name varchar(128));
INSERT INTO tblHierarchy VALUES (1, NULL, '1');
INSERT INTO tblHierarchy VALUES (2, NULL, '2');
INSERT INTO tblHierarchy VALUES (3, NULL, '3');
INSERT INTO tblHierarchy VALUES (4, 1, '1.1');
INSERT INTO tblHierarchy VALUES (5, 1, '1.2');
INSERT INTO tblHierarchy VALUES (6, 4, '1.1.1');
WITH Parent AS
(
SELECT
ID,
ParentID,
Name AS Path
FROM
tblHierarchy
WHERE
ParentID IS NULL
UNION ALL
SELECT
TH.ID,
TH.ParentID,
CONVERT(varchar(128), Parent.Path + '/' + TH.Name) AS Path
FROM
tblHierarchy TH
INNER JOIN
Parent
ON
Parent.ID = TH.ParentID
)
SELECT * FROM Parent
ВЫВОД:
ID ParentID Path
1 NULL 1
2 NULL 2
3 NULL 3
4 1 1/1.1
5 1 1/1.2
6 4 1/1.1/1.1.1
Ответ 2
Просто FYI. SQL Server 2008 поддерживает новый тип данных Иерархический идентификатор.
Ответ 3
Используя оба, я обнаружил, что CONNECT BY несколько более гибкий и более простой в использовании, чем CTE. Вопрос не отличается от того, который я ответил несколько недель назад. См. здесь для краткого сравнения CONNECT BY и CTE и здесь для примера запроса с использованием CTE.
Ответ 4
Прочтите это:
http://www.sitepoint.com/article/hierarchical-data-database/2/
Он должен дать вам несколько идей...
Ответ 5
в SQL Server 2005 для этого можно использовать Common Table Expressions (CTE).
Ответ 6
Чтобы пересечь глубину иерархии сначала, а затем следующий уровень брата, CTE может использоваться:
declare @tempTable TABLE
(
ORGUID int,
ORGNAME nvarchar(100),
PARENTORGUID int,
ORGPATH nvarchar(max)
)
;WITH RECORG(ORGuid, ORGNAME, PARENTORGUID, ORGPATH)
as
(
select
org.UID,
org.Name,
org.ParentOrganizationUID,
dbo.fGetOrganizationBreadcrumbs(org.UID)
from Organization org
where org.UID =1
union all
select
orgRec.UID,
orgRec.Name,
orgRec.ParentOrganizationUID,
dbo.fGetOrganizationBreadcrumbs(orgRec.UID)
from Organization orgRec
inner join RECORG recOrg on orgRec.ParentOrganizationUID = recOrg.ORGuid
)
insert into @tempTable(ORGUID, ORGNAME, PARENTORGUID,ORGPATH)
select ORGUID, ORGNAME, PARENTORGUID,ORGPATH
from RECORG rec
select *
from @tempTable where ORGUID in(select MIN(tt.ORGUID)
from @tempTable tt
group by tt.PARENTORGUID)