Sql 与层次顺序和缩进空间相关的查询
输入表:区域Sql 与层次顺序和缩进空间相关的查询,sql,sql-server,database,Sql,Sql Server,Database,输入表:区域 +---------------+---------------+---------- +-----------+ | Child | Parent | Level | levelname| +---------------+---------------+---------- +-----------+ | All Region | All Region | 1 | nation
+---------------+---------------+---------- +-----------+
| Child | Parent | Level | levelname|
+---------------+---------------+---------- +-----------+
| All Region | All Region | 1 | national |
| Africa Region | All Region | 2 | region |
| America | All Region | 2 | region |
| Asia | All Region | 2 | region |
| Europe Region | All Region | 2 | region |
| Africa | Africa Region | 3 | Subregion |
| Asia Pacific | Asia | 3 | Subregion |
| Europe | Europe Region | 3 | Subregion |
| North America | America | 3 | Subregion |
| South America | America | 3 | Subregion |
| Argentina | South America | 4 | Country |
| Australia | Asia Pacific | 4 | Country |
| Pakistan | Asia Pacific | 4 | Country |
| South Africa | Africa | 4 | Country |
| Tunisia | Africa | 4 | Country |
| Uruguay | South America | 4 | Country |
+-------------------------------------------------------+
在这里,区域分为4个级别
- 所有地区
- 区域
- 次区域
- 国家
National
Region_1
SubRegion_1_1
Country_1_1_1
Country_1_1_2
SubRegion_1_2
Country_1_2_1
Country_1_2_2
Country_1_2_3
Country_1_2_4
Region_2
…. And so on.
输出有一些缩进的空格来显示视觉效果,我不知道如何开始查询。您需要递归cte来获取层次结构中的数据
-- populate test data
DECLARE @tbl TABLE (Child VARCHAR(100), Parent VARCHAR(100), Level INT, LevelName VARCHAR(100))
INSERT INTO @tbl
VALUES
('AllRegion' ,'AllRegion' ,1 ,'national')
,('AfricaRegion' ,'AllRegion' ,2 ,'region')
,('America' ,'AllRegion' ,2 ,'region')
,('Asia' ,'AllRegion' ,2 ,'region')
,('EuropeRegion' ,'AllRegion' ,2 ,'region')
,('Africa' ,'AfricaRegion' ,3 ,'Subregion')
,('AsiaPacific' ,'Asia' ,3 ,'Subregion')
,('Europe' ,'EuropeRegion' ,3 ,'Subregion')
,('NorthAmerica' ,'America' ,3 ,'Subregion')
,('SouthAmerica' ,'America' ,3 ,'Subregion')
,('Argentina' ,'SouthAmerica' ,4 ,'Country')
,('Australia' ,'AsiaPacific' ,4 ,'Country')
,('Pakistan' ,'AsiaPacific' ,4 ,'Country')
,('SouthAfrica' ,'Africa' ,4 ,'Country')
,('Tunisia' ,'Africa' ,4 ,'Country')
,('Uruguay' ,'SouthAmerica' ,4 ,'Country')
-- use this query
;WITH Cte AS
(
SELECT *
,ROW_NUMBER() OVER (PARTITION BY t.LevelName, t.Parent ORDER BY t.Level) AS RowNo -- assing a number to use for sorting
from @tbl t
),
Final AS
(
SELECT t.child, t.Parent, t.Level
,CAST(RowNo AS VARCHAR(MAX)) AS SortBy -- this will be used for sorting.
FROM Cte t
WHERE t.level = 1
UNION ALL
SELECT c.child, c.parent, c.level
,CAST(p.SortBy + CAST(c.RowNo AS VARCHAR(MAX))AS VARCHAR(MAX)) AS SortBy -- keep adding the levels to the sort order
FROM Cte c
INNER JOIN Final p On c.Parent = p.child
AND c.Level > 1 -- this is required as the top parent is not set as NULL
)
SELECT Child
,SortBy
,SPACE(Level * 4 ) + Child AS HierarcyText
FROM Final
ORDER BY SortBy
OPTION(MAXRECURSION 0)
希望这对你有帮助
结果:
;with cte as (
select
Child, Parent, Level, LevelName,
rn = CONVERT(nvarchar(max), ROW_NUMBER() Over (Partition By Level Order By Child) )
from Regions where Level = 1
union all
select
r.Child, r.Parent, r.Level, r.LevelName,
rn = rn + '_' + CONVERT(nvarchar(max), ROW_NUMBER() Over (Partition By r.Level Order By r.Child) )
from Regions r
inner join cte
on r.Level = (cte.Level + 1) and
r.Parent = cte.Child
)
select *
from cte
order by rn
搜索
递归cte
select
case when ROW_NUMBER() OVER(ORDER BY r2.levelname DESC) = 1 then r1.levelname else '' end as L1,
case when ROW_NUMBER() OVER(PARTITION BY r2.Child ORDER BY r2.Child DESC) = 1 then r2.Child else '' end as L2,
case when ROW_NUMBER() OVER(PARTITION BY r3.Child ORDER BY r3.Child DESC) = 1 then r3.Child else '' end as L3,
case when ROW_NUMBER() OVER(PARTITION BY r4.Child ORDER BY r4.Child DESC) = 1 then r4.Child else '' end as L4
from #Regions r1
inner join #Regions r2 on r1.Child = r2.Parent and r2.level = 2
inner join #Regions r3 on r2.Child = r3.Parent and r3.level = 3
inner join #Regions r4 on r3.Child = r4.Parent and r4.level = 4
where r1.level = 1
order by r1.levelname, r2.Child, r3.Child, r4.Child
;with cte as (
select
Child, Parent, Level, LevelName,
rn = CONVERT(nvarchar(max), ROW_NUMBER() Over (Partition By Level Order By Child) )
from Regions where Level = 1
union all
select
r.Child, r.Parent, r.Level, r.LevelName,
rn = rn + '_' + CONVERT(nvarchar(max), ROW_NUMBER() Over (Partition By r.Level Order By r.Child) )
from Regions r
inner join cte
on r.Level = (cte.Level + 1) and
r.Parent = cte.Child
)
select *
from cte
order by rn