2017-04-04 30 views
2

我有這些記錄的表:SQL Server存儲過程 - 如何使用樹格式對記錄進行排序?

+----+-------------+---------+ 
| ID | Name  | ParentID| 
+----+-------------+---------+ 
| 1 | Item 1  | -1 | 
| 2 | Item 2  | -1 | 
| 3 | Item 1.1 | 1 | 
| 4 | Item 1.2 | 1 | 
| 5 | Item 2.1 | 2 | 
| 6 | Item 1.1.1 | 3 | 
| 7 | Item 1.2.1 | 4 | 
| 8 | Item 2.2 | 2 | 
| 9 | Item 1.1.1.1| 6 | 
+----+-------------+---------+ 

我想選擇與樹格式的記錄。

如何使用存儲過程獲得像下表一樣的結果? Name列的值是暫時的,它可以是任何字。

+----+-------------+---------+ 
| ID | Name  | ParentID| 
+----+-------------+---------+ 
| 1 | Item 1  | -1 | 
| 3 | Item 1.1 | 1 | 
| 6 | Item 1.1.1 | 3 | 
| 9 | Item 1.1.1.1| 6 | 
| 4 | Item 1.2 | 1 | 
| 7 | Item 1.2.1 | 4 | 
| 2 | Item 2  | -1 | 
| 5 | Item 2.1 | 2 | 
| 8 | Item 2.2 | 2 | 
+----+-------------+---------+ 

對不起,我是初學者的存儲過程。所以我不知道如何得到如上表所示的結果。

感謝您閱讀

+0

mysql或MS SQL-Server? – Jens

+0

MS SQL-Server bro。 –

+0

不要添加與您的問題無關的標籤 – Jens

回答

0

我覺得父節點必須在它的子節點之前。 這裏是我的查詢

DECLARE @SampleData AS TABLE(ID int, Name varchar(20) , ParentID int) 

INSERT INTO @SampleData VALUES ( 1 ,' Item 1', -1 ) 
INSERT INTO @SampleData VALUES (2 ,' Item 2'  , -1 ) 
INSERT INTO @SampleData VALUES ( 3 ,' Item 1.1' , 1 ) 
INSERT INTO @SampleData VALUES ( 4 ,' Item 1.2' , 1 ) 
INSERT INTO @SampleData VALUES ( 5 ,' Item 2.1' , 2 ) 
INSERT INTO @SampleData VALUES ( 6 ,' Item 1.1.1' , 4 ) 
INSERT INTO @SampleData VALUES ( 7 ,' Item 1.2.1' , 6 ) 
INSERT INTO @SampleData VALUES ( 8 ,' Item 2.2' , 2 ) 

;with cte as (
    select t.Id, t.Name, t.ParentID, 1 as lev, t.Id AS RootId 
    from @SampleDAta t 
    where t.ParentID = -1 
    union all 
    select t.ID, t.Name,t.ParentID,cte.lev +1, cte.RootId 
    from cte 
    INNER JOIN @SampleDAta t on t.ParentID = cte.Id 
    ) 
SELECT c.Id, c.Name, c.ParentID FROM cte c 
ORDER BY c.RootId, c.lev 
OPTION (MAXRECURSION 0) 

結果:

enter image description here

如果你想有點像一個深度搜索樹,我可以通過一個函數

CREATE TABLE SampleData (ID int, Name varchar(20) , ParentID int) 

INSERT INTO SampleData VALUES ( 1 ,' Item 1', -1 ) 
INSERT INTO SampleData VALUES (2 ,' Item 2'  , -1 ) 
INSERT INTO SampleData VALUES ( 3 ,' Item 1.1' , 1 ) 
INSERT INTO SampleData VALUES ( 4 ,' Item 1.2' , 1 ) 
INSERT INTO SampleData VALUES ( 5 ,' Item 2.1' , 2 ) 
INSERT INTO SampleData VALUES ( 6 ,' Item 1.1.1' , 3 ) 
INSERT INTO SampleData VALUES ( 7 ,' Item 1.2.1' , 4 ) 
INSERT INTO SampleData VALUES ( 8 ,' Item 2.2' , 2 ) 

做現在創建功能

CREATE FUNCTION DisplayTree 
(
    @RootId int 
) 
RETURNS 
@result TABLE (
    ID int, Name varchar(20) , ParentID int 
    ) 
AS 
BEGIN 
    DECLARE @Temp AS TABLE 
    (
     ID int, Name varchar(20) , ParentID int 
    ) 
    INSERT INTO @Temp SELECT * FROM SampleData WHERE ParentID = @RootId 

    WHILE(EXISTS(SELECT 1 FROM @Temp t)) 
    BEGIN 
     DECLARE @CurrentRootId int 
     SELECT TOP 1 @CurrentRootId = t.ID FROM @Temp t ORDER BY t.ID ASC 
     INSERT INTO @result SELECT * FROM @Temp t WHERE t.ID = @CurrentRootId 
     DELETE FROM @Temp WHERE ID = @CurrentRootId 

     INSERT INTO @result SELECT * FROM dbo.DisplayTree(@CurrentRootId) 
    END 

    RETURN ; 
END 
GO 

AND執行功能

SELECT * FROM dbo.DisplayTree(-1) 
+0

表格的值是動態的!它會隨時插入,編輯或刪除! –

+0

更多, 1.1.1'爲'1.1',而非限制級別(1.1.1.1或更多) –

+0

我剛剛使用了一個遞歸函數來從Id和ParentId計算名稱並不重要從您的數據中,項目1.1.1的父項是項目與Id'4',它是項目1.2 – TriV

0

您需要拆分到n的列的列數,然後需要使用ORDER BY那些列。

模式:

CREATE TABLE #TAB(ID INT, Name VARCHAR(20),ParentID INT) 

INSERT INTO #TAB 
SELECT 1, 'Item 1', -1 
UNION ALL 
SELECT 2, 'Item 2' , -1 
UNION ALL 
SELECT 3, 'Item 1.1' , 1 
UNION ALL 
SELECT 4, 'Item 1.2' , 1 
UNION ALL 
SELECT 5, 'Item 2.1' , 2 
UNION ALL 
SELECT 6, 'Item 1.1.1', 4 
UNION ALL 
SELECT 7, 'Item 1.2.1', 6 
UNION ALL 
SELECT 8, 'Item 2.2', 2 

我轉換NameXML,然後我使用XML方法value

;WITH CTE AS 
( 
    SELECT 
     ID, 
     Name, 
     ParentID, 
     CAST('<M>'+REPLACE (REPLACE(Name,' ','.'),'.','</M><M>')+'</M>' AS XML) 
     AS XML_SPLT 
    FROM #TAB 
) 
SELECT 
    ID, 
    Name, 
    ParentID, 
    XML_SPLT.value('/M[1]', 'varchar(50)') As P0, 
    XML_SPLT.value('/M[2]', 'int') As P1, 
    XML_SPLT.value('/M[3]', 'int') As P2, 
    XML_SPLT.value('/M[4]', 'int') As P3 

FROM CTE 
ORDER BY P0,P1,P2,P3 
GO 

這會給你的命令,你期待做列的標籤。

+----+------------+----------+------+----+------+------+ 
| ID | Name | ParentID | P0 | P1 | P2 | P3 | 
+----+------------+----------+------+----+------+------+ 
| 1 | Item 1  |  -1 | Item | 1 | NULL | NULL | 
| 3 | Item 1.1 |  1 | Item | 1 | 1 | NULL | 
| 6 | Item 1.1.1 |  4 | Item | 1 | 1 | 1 | 
| 4 | Item 1.2 |  1 | Item | 1 | 2 | NULL | 
| 7 | Item 1.2.1 |  6 | Item | 1 | 2 | 1 | 
| 2 | Item 2  |  -1 | Item | 2 | NULL | NULL | 
| 5 | Item 2.1 |  2 | Item | 2 | 1 | NULL | 
| 8 | Item 2.2 |  2 | Item | 2 | 2 | NULL | 
+----+------------+----------+------+----+------+------+ 
+0

哦,'Name'列的值是臨時的,它可以是'ANY WORD'。 –

+0

我設置了數值格式'Item x.x.x',使大家容易理解我需要的第二張表! :( –

+0

您是否用您的實際數據嘗試了它?@AIVN –

相關問題