Sql server 像treeview一样进行查询
兄弟们,你能帮我吗?谢谢Sql server 像treeview一样进行查询,sql-server,Sql Server,兄弟们,你能帮我吗?谢谢 Table A Id Name IdParent 1 Operation Null 2 Developer 1 3 Android 2 4 IOS 2 预期结果: ID Name
Table A
Id Name IdParent
1 Operation Null
2 Developer 1
3 Android 2
4 IOS 2
预期结果:
ID Name
1 +Operation
2 +------ Developer
3 +------------Android
4 +------------ IOS
通过在递归构建期间添加序列,您可以轻松地创建适当的表示序列和嵌套
Declare @YourTable table (id int,IdParent int,Name varchar(50))
Insert into @YourTable values
( 1, NULL,'Operation')
,( 2, 1 ,'Developer')
,( 3, 2 ,'Android')
,( 4, 2 ,'IOS')
,( 5, 1 ,'Poet')
,( 6, 5 ,'Limerick')
,( 7, 5 ,'Haiku')
Declare @Top int = null --<< Sets top of Hier Try 2
Declare @Nest varchar(25) = '|-----' --<< Optional: Added for readability
;with cteP as (
Select Seq = cast(10000+Row_Number() over (Order by Name) as varchar(500))
,ID
,IdParent
,Lvl=1
,Name
From @YourTable
Where IsNull(@Top,-1) = case when @Top is null then isnull(IdParent ,-1) else ID end
Union All
Select Seq = cast(concat(p.Seq,'.',10000+Row_Number() over (Order by r.Name)) as varchar(500))
,r.ID
,r.IdParent
,p.Lvl+1
,r.Name
From @YourTable r
Join cteP p on r.IdParent = p.ID)
Select A.ID
,A.IdParent
,A.Lvl
,Name = Replicate(@Nest,A.Lvl-1) + A.Name
From ctep A
Order By A.Seq
--查询使用递归CTE,最后使用递归级别的REPLICATE
添加连字符数
WITH recCTE AS
(
SELECT Id, Name, 1 AS Lvl, CAST(REPLACE(STR(ROW_NUMBER() OVER (ORDER BY Id),5),' ','0') AS VARCHAR(MAX)) AS Seq
FROM @mockup
WHERE IdParent IS NULL
UNION ALL
SELECT m.Id,m.Name,r.Lvl +1,r.Seq + '.' + REPLACE(STR(ROW_NUMBER() OVER (ORDER BY m.Id),5),' ','0')
FROM @mockup AS m
INNER JOIN recCTE AS r ON m.IdParent=r.Id
)
SELECT *
,'+' + REPLICATE('-',Lvl*4) + Name
FROM recCTE
ORDER BY Seq
结果
+----+-----------+-----+----------------------+
| Id | Name | Lvl | (Kein Spaltenname) |
+----+-----------+-----+----------------------+
| 1 | Operation | 1 | +----Operation |
+----+-----------+-----+----------------------+
| 2 | Developer | 2 | +--------Developer |
+----+-----------+-----+----------------------+
| 3 | Android | 3 | +------------Android |
+----+-----------+-----+----------------------+
| 4 | IOS | 3 | +------------IOS |
+----+-----------+-----+----------------------+
以下是另一个版本:
WITH RawData AS (
SELECT 1 AS Id, 'Operation' AS Name, CONVERT(INT, NULL) AS IdParent
UNION ALL
SELECT 2 AS Id, 'Developer' AS Name, 1 AS IdParent
UNION ALL
SELECT 3 AS Id, 'Android' AS Name, 2 AS IdParent
UNION ALL
SELECT 4 AS Id, 'IOS' AS Name, 2 AS IdParent),
Depth AS (
SELECT
Id,
1 AS depth,
IdParent
FROM
RawData
UNION ALL
SELECT
d.Id,
d.depth + 1,
r.IdParent
FROM
Depth d
INNER JOIN RawData r ON r.Id = d.IdParent),
MaxDepth AS (
SELECT
Id,
MAX(depth) AS depth
FROM
Depth
GROUP BY
Id)
SELECT
r.Id,
'+' + REPLICATE('----', m.depth - 1) + r.Name AS Name
FROM
RawData r
INNER JOIN MaxDepth m ON m.Id = r.Id;
结果:
Id Name
1 +Operation
2 +----Developer
3 +--------Android
4 +--------IOS
@Shnugo谢谢。但我确实忘记了Seq的订单我不确定这是否重要。。。递归CTE是一个隐藏的RBAR,结果是逐行创建的。。。按级别排序应该足够了。。。无论如何,如果有一个特殊的订单,这将必须在输入数据已经。。。有趣的是,我们的答案几乎是完全一样的,我想你是几秒钟前。。。你正在报道更多的好东西。。。否则这可能是过量的。。。我应该删除我的吗?@Shnugo查看我的更新答案,如果只有一条路径,但如果序列有助于正确的选择nesting@Shnugo没有必要删除您的答案。我可能已经阅读了OPs问题,我用一种稍微不同的方法重新打开了它,只是为了让KISS解决方案保持可读性…str()是我10000+行的一个很好的替代品。我可以接受它,只是另一种想法。按ID排序可能会产生意外结果。请注意,在我的示例中,俳句在Limerick之前,不考虑ID@JohnCappelletti我避开了名字。。。两个相同的名字呢?
WITH RawData AS (
SELECT 1 AS Id, 'Operation' AS Name, CONVERT(INT, NULL) AS IdParent
UNION ALL
SELECT 2 AS Id, 'Developer' AS Name, 1 AS IdParent
UNION ALL
SELECT 3 AS Id, 'Android' AS Name, 2 AS IdParent
UNION ALL
SELECT 4 AS Id, 'IOS' AS Name, 2 AS IdParent),
Depth AS (
SELECT
Id,
1 AS depth,
IdParent
FROM
RawData
UNION ALL
SELECT
d.Id,
d.depth + 1,
r.IdParent
FROM
Depth d
INNER JOIN RawData r ON r.Id = d.IdParent),
MaxDepth AS (
SELECT
Id,
MAX(depth) AS depth
FROM
Depth
GROUP BY
Id)
SELECT
r.Id,
'+' + REPLICATE('----', m.depth - 1) + r.Name AS Name
FROM
RawData r
INNER JOIN MaxDepth m ON m.Id = r.Id;
Id Name
1 +Operation
2 +----Developer
3 +--------Android
4 +--------IOS