Woo*_*460 45 sql-server common-table-expression
我需要以特定的方式获得树的有序层次结构.有问题的表看起来有点像这样(所有ID字段都是uniqueidentifiers,为了示例,我简化了数据):
EstimateItemID EstimateID ParentEstimateItemID ItemType
-------------- ---------- -------------------- --------
1 A NULL product
2 A 1 product
3 A 2 service
4 A NULL product
5 A 4 product
6 A 5 service
7 A 1 service
8 A 4 product
树形结构的图形视图(*表示"服务"):
A
___/ \___
/ \
1 4
/ \ / \
2 7* 5 8
/ /
3* 6*
使用此查询,我可以获得层次结构(只是假装'A'是一个唯一标识符,我知道它不在现实生活中):
DECLARE @EstimateID uniqueidentifier
SELECT @EstimateID = 'A'
;WITH temp as(
SELECT * FROM EstimateItem
WHERE EstimateID = @EstimateID
UNION ALL
SELECT ei.* FROM EstimateItem ei
INNER JOIN temp x ON ei.ParentEstimateItemID = x.EstimateItemID
)
SELECT * FROM temp
Run Code Online (Sandbox Code Playgroud)
这给了我EstimateID'A'的子项,但按照它出现在表中的顺序.即:
EstimateItemID
--------------
1
2
3
4
5
6
7
8
不幸的是,我需要的是一个有序的层次结构,其结果集遵循以下约束:
1. each branch must be grouped 2. records with ItemType 'product' and parent are the top node 3. records with ItemType 'product' and non-NULL parent grouped after top node 4. records with ItemType 'service' are bottom node of a branch
所以,在这个例子中,我需要结果的顺序是:
EstimateItemID
--------------
1
2
3
7
4
5
8
6
我需要在查询中添加什么才能完成此操作?
Fab*_*bio 77
试试这个:
;WITH items AS (
SELECT EstimateItemID, ItemType
, 0 AS Level
, CAST(EstimateItemID AS VARCHAR(255)) AS Path
FROM EstimateItem
WHERE ParentEstimateItemID IS NULL AND EstimateID = @EstimateID
UNION ALL
SELECT i.EstimateItemID, i.ItemType
, Level + 1
, CAST(Path + '.' + CAST(i.EstimateItemID AS VARCHAR(255)) AS VARCHAR(255))
FROM EstimateItem i
INNER JOIN items itms ON itms.EstimateItemID = i.ParentEstimateItemID
)
SELECT * FROM items ORDER BY Path
Run Code Online (Sandbox Code Playgroud)
with Path- 行按父节点排序
如果你想排序的childNodes ItemType每个级别的,比你可以玩Level和SUBSTRING的Path列....
这里有SQLFiddle数据样本
pto*_*bro 14
这是Fabio从上面提出的伟大创意的补充.就像我在回复原帖时说的那样.我使用更常见的数据,表名和字段重新发布了他的想法,以便其他人更容易理解.
谢谢法比奥!顺便说一句好名字.
首先要使用的一些数据:
CREATE TABLE tblLocations (ID INT IDENTITY(1,1), Code VARCHAR(1), ParentID INT, Name VARCHAR(20));
INSERT INTO tblLocations (Code, ParentID, Name) VALUES
('A', NULL, 'West'),
('A', 1, 'WA'),
('A', 2, 'Seattle'),
('A', NULL, 'East'),
('A', 4, 'NY'),
('A', 5, 'New York'),
('A', 1, 'NV'),
('A', 7, 'Las Vegas'),
('A', 2, 'Vancouver'),
('A', 4, 'FL'),
('A', 5, 'Buffalo'),
('A', 1, 'CA'),
('A', 10, 'Miami'),
('A', 12, 'Los Angeles'),
('A', 7, 'Reno'),
('A', 12, 'San Francisco'),
('A', 10, 'Orlando'),
('A', 12, 'Sacramento');
Run Code Online (Sandbox Code Playgroud)
现在递归查询:
-- Note: The 'Code' field isn't used, but you could add it to display more info.
;WITH MyCTE AS (
SELECT ID, Name, 0 AS TreeLevel, CAST(ID AS VARCHAR(255)) AS TreePath
FROM tblLocations T1
WHERE ParentID IS NULL
UNION ALL
SELECT T2.ID, T2.Name, TreeLevel + 1, CAST(TreePath + '.' + CAST(T2.ID AS VARCHAR(255)) AS VARCHAR(255)) AS TreePath
FROM tblLocations T2
INNER JOIN MyCTE itms ON itms.ID = T2.ParentID
)
-- Note: The 'replicate' function is not needed. Added it to give a visual of the results.
SELECT ID, Replicate('.', TreeLevel * 4)+Name 'Name', TreeLevel, TreePath
FROM MyCTE
ORDER BY TreePath;
Run Code Online (Sandbox Code Playgroud)