iT邦幫忙

2

趣味SQL,在資料庫查詢功能樹狀圖用畫線方式來表示

sql
  • 分享至 

  • xImage
  •  

這是以前考古題發問的,因為最近被挖出來,以下我的SQL解法,參考看看

原始貼文:傳送門


3/3 新增線條符合版+註解說明 /images/emoticon/emoticon06.gif
https://ithelp.ithome.com.tw/upload/images/20260303/20061369FLq7vMNgK3.png

drop table if exists #Tmp

create table #Tmp(
 item nvarchar(50)
 ,part nvarchar(50)
)

insert into #Tmp
values('11401-3412-1', '90514-20299O')
,('11409-3320', '11409-3321-A')
,('11409-3320', '11409-3322')
,('11409-3416-1', 'L608M')
,('11413-2400-1', '11413-3400-1')
,('11413-2400-1', '11502-3502-A')
,('11413-3400-1', '11409-3416-1')
,('11413-3400-1', '11413-3410-1')
,('11413-3410-1', '11401-3412-1')
,('11413-3410-1', '11413-3411-1')
,('11413-3411-1', '90505-45238O')
,('11426-2300-A', '11409-3320')
,('11426-2300-A', '11409-3332-B')
,('11426-2300-A', '11409-3333-B')
,('11426-2300-A', '11426-2311-2')
,('11426-2300-A', '14402-3335-B')
,('11426-2300-A', '41101-3334')
,('11426-2311-2', '11426-3313')
,('11426-3207', '90512-16348E')
,('11433-2000-D', '11426-2950-A')
,('11433-2000-D', '11433-2100-C')
,('11433-2100-C', '11101-3503')
,('11433-2100-C', '11101-3504')
,('11433-2100-C', '11103-3702')
,('11433-2100-C', '11413-2400-1')
,('11433-2100-C', '11413-2501-A')
,('11433-2100-C', '11413-3400-1')
,('11433-2100-C', '11426-2300-A')
,('11433-2100-C', '11433-2200-A')
,('11433-2100-C', '11502-2520-A')
,('11433-2100-C', '11502-2531-A')
,('11433-2100-C', '11502-3611')
,('11433-2100-C', '11502-3613')
,('11433-2100-C', '11502-3615')
,('11433-2100-C', '12501-3621')
,('11433-2100-C', '12501-3901')
,('11433-2100-C', '12501-3902-A')
,('11433-2100-C', '14301-3701')
,('11433-2100-C', 'CF241249-G01')
,('11433-2200-A', '11401-3202-A')
,('11433-2200-A', '11426-3207')
,('11433-2200-A', '11433-2201')
,('11433-2200-A', '11433-2P')
,('11433-2201', '90504-29330E')
,('11433-2P', '11401-3203')
,('11433-2P', '11401-3204')
,('11433-2P', '11433-3209')
,('11433-2P', '11502-2205')
,('11502-2520-A', '11502-2521-1')
,('11502-2520-A', '11502-2522-1')
,('11502-2520-A', '11502-3523-A')

;WITH ChildInfo AS (
	--先產生額外資訊,紀錄節點及順序
    SELECT item,
    part,
    ROW_NUMBER() OVER (PARTITION BY item ORDER BY part) AS child_pos,
    COUNT(*) OVER (PARTITION BY item) AS cnt
    FROM #Tmp a
)
, Tree AS (
	--首先第一層查詢
	SELECT 
	--父節點
	a.item,
	--子節點
	a.part,
	--起始階層
	1 AS lvl,
	--將此子節點名稱,先轉為統一格式
	CAST(a.part AS varchar(200)) AS display,
	--上層節點紀錄
	CAST('' AS varchar(200)) AS SubPrefix,
	--同階層判斷,最後子節點紀錄【└】,不是最後子節點紀錄【├】
	CAST((
		case when b.child_pos <> b.cnt
		then '├'
		else '└'
		end
	) AS varchar(200)) AS prefix,
	--目前節點序
	Convert(int,b.child_pos) child_pos,
	--總節點序
	Convert(int,b.cnt) cnt,
	--樹狀圖排序
	CAST(Right('00' + CAST(b.child_pos AS varchar(10)),3) AS varchar(50)) AS path
	FROM #Tmp a
	inner join ChildInfo b on a.part = b.part
	--起始節點的設定
	WHERE a.item = '11433-2000-D'

	--遞迴UNION標準作法
	UNION ALL

	--開始第二層後的遞迴查詢
	SELECT 
	--父節點
	ci.item,
	--子節點
	ci.part,
	--目前階層
	tr.lvl + 1,
	--將此子節點名稱,先轉為統一格式
	CAST(ci.part AS varchar(200)),
	--上層節點紀錄
	tr.prefix,
	
	CAST(
		--將上層節點紀錄轉換,【└】轉為【空白】代表下方節數結束,【├】轉為【│】代表下方節點還有
		Replace(Replace(tr.prefix,'└',' '),'├','│') + 
		--同階層判斷,最後子節點紀錄【└】,不是最後子節點紀錄【├】
		CASE 
			WHEN ci.child_pos <> ci.cnt 
			THEN '├'
			ELSE '└'
		END
	AS varchar(200)),

	--目前節點序
	CAST(ci.child_pos as int),
	--總節點序
	ci.cnt,
	--樹狀圖排序
	CAST(tr.path + '.' + Right('00' + CAST(ci.child_pos AS varchar(10)),3) AS varchar(50))
	FROM Tree tr
	INNER JOIN ChildInfo ci ON tr.part = ci.item
)
--最後展出樹狀圖資料
SELECT 
	prefix 
	+ NCHAR(0x2775 + lvl)
	+ display AS TreeLine
	,SubPrefix
	,prefix
	,child_pos
	,cnt
	,path
FROM Tree
ORDER BY path;


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言