Sql-Server

父子樹層次順序

  • December 15, 2017

我必須在 SQL Server 2008 R2 中跟踪數據。SQLFiddle

架構:

創建表 [dbo].[ICFilters](
[ICFilterID] [int] IDENTITY(1,1) 非空,
[ParentID] [int] NOT NULL DEFAULT 0,
[FilterDesc] [varchar](50) 非空,
[Active] [tinyint] NOT NULL DEFAULT 1,
約束 [PK_ICFilters] 主鍵集群
([ICFilterID] ASC)與
PAD_INDEX = 關閉,
STATISTICS_NORECOMPUTE = 關閉,
IGNORE_DUP_KEY = 關閉,
ALLOW_ROW_LOCKS = 開,
ALLOW_PAGE_LOCKS = ON
) 開 [主要]
) 開 [主要]

插入 [dbo].[ICFilters] (ParentID,FilterDesc,Active)
價值觀
(0,'產品類型',1),
(1, 'ProdSubType_1', 1),
(1, 'ProdSubType_2', 1),
(1, 'ProdSubType_3', 1),
(1, 'ProdSubType_4', 1),
(2, 'PST_1.1', 1),
(2, 'PST_1.2', 1),
(2, 'PST_1.3', 1),
(2, 'PST_1.4', 1),
(2, 'PST_1.5', 1),
(2, 'PST_1.6', 1),
(2, 'PST_1.7', 0),
(3, 'PST_2.1', 1),
(3, 'PST_2.2', 0),
(3, 'PST_2.3', 1),
(3, 'PST_2.4', 1),
(14, 'PST_2.2.1', 1),
(14, 'PST_2.2.2', 1),
(14, 'PST_2.2.3', 1),
(3, 'PST_2.8', 1)

桌子:

| ICFILTERID | 家長 ID | 過濾器 | 活躍 |
--------------------------------------------------
| 1 | 0 | 產品類型 | 1 |
| 2 | 1 | ProdSubType_1 | 1 |
| 3 | 1 | ProdSubType_2 | 1 |
| 4 | 1 | ProdSubType_3 | 1 |
| 5 | 1 | ProdSubType_4 | 1 |
| 6 | 2 | PST_1.1 | 1 |
| 7 | 2 | PST_1.2 | 1 |
| 8 | 2 | PST_1.3 | 1 |
| 9 | 2 | PST_1.4 | 1 |
| 10 | 2 | PST_1.5 | 1 |
| 11 | 2 | PST_1.6 | 1 |
| 12 | 2 | PST_1.7 | 0 |
| 13 | 3 | PST_2.1 | 1 |
| 14 | 3 | PST_2.2 | 0 |
| 15 | 3 | PST_2.3 | 1 |
| 16 | 3 | PST_2.4 | 1 |
| 17 | 14 | PST_2.2.1 | 1 |
| 18 | 14 | PST_2.2.2 | 1 |
| 19 | 14 | PST_2.2.3 | 1 |
| 20 | 3 | PST_2.8 | 1 |

每行都有其父項的 ID 和根的parentid = 0. s 只是範例描述,FilterDesc因此我無法嘗試解析這些描述以進行排序。

問題

是否可以以樹狀方式選擇所有行?如果是這樣,怎麼做?當我說“樹狀”時,我的意思是遞歸地選擇父項,然後是其所有子項,然後是每個子項的所有子項,依此類推。深度優先樹遍歷。

我和我的朋友們已經嘗試過,但我們沒有找到有效的解決方案,但會繼續嘗試。我對 sql 相當陌生,所以也許這可以很容易地完成,我只是讓事情變得比必要的更難。

範例(所需)輸出:

| ICFILTERID | 家長 ID | 過濾器 | 活躍 |
--------------------------------------------------
| 1 | 0 | 產品類型 | 1 |
| 2 | 1 | ProdSubType_1 | 1 |
| 6 | 2 | PST_1.1 | 1 |
| 7 | 2 | PST_1.2 | 1 |
| 8 | 2 | PST_1.3 | 1 |
| 9 | 2 | PST_1.4 | 1 |
| 10 | 2 | PST_1.5 | 1 |
| 11 | 2 | PST_1.6 | 1 |
| 12 | 2 | PST_1.7 | 0 |
| 3 | 1 | ProdSubType_2 | 1 |
| 13 | 3 | PST_2.1 | 1 |
| 14 | 3 | PST_2.2 | 0 |
| 17 | 14 | PST_2.2.1 | 1 |
| 18 | 14 | PST_2.2.2 | 1 |
| 19 | 14 | PST_2.2.3 | 1 |
| 15 | 3 | PST_2.3 | 1 |
| 16 | 3 | PST_2.4 | 1 |
| 20 | 3 | PST_2.8 | 1 |
| 4 | 1 | ProdSubType_3 | 1 |
| 5 | 1 | ProdSubType_4 | 1 |

好的,足夠多的腦細胞已經死亡。

SQL小提琴

WITH cte AS
(
 SELECT 
   [ICFilterID], 
   [ParentID],
   [FilterDesc],
   [Active],
   CAST(0 AS varbinary(max)) AS Level
 FROM [dbo].[ICFilters]
 WHERE [ParentID] = 0
 UNION ALL
 SELECT 
   i.[ICFilterID], 
   i.[ParentID],
   i.[FilterDesc],
   i.[Active],  
   Level + CAST(i.[ICFilterID] AS varbinary(max)) AS Level
 FROM [dbo].[ICFilters] i
 INNER JOIN cte c
   ON c.[ICFilterID] = i.[ParentID]
)

SELECT 
 [ICFilterID], 
 [ParentID],
 [FilterDesc],
 [Active]
FROM cte
ORDER BY [Level];

以上對我來說似乎無法正常工作。想像一下帶有 facebook 類型數據的 2 表設置。表 1,有 PostId + you 其他欄位。PostId 是自動遞增的,顯然在您的界面中,您將對 DESC 進行排序以使最新文章位於頂部。

現在是評論表。表2 此表CommentId 為主鍵,自動編號。在您的 gui 中,您希望將其顯示為 ASC,以便在閱讀執行緒時,它是有意義的。(最舊的(較小的數字)在頂部)表 2 中的其他重要鍵是:PostId(FK 回到文章)和 ParentId(FK 到 CommentId)如果這是文章的“根”評論,ParentId 將為 NULL。如果有人回複評論,則 parentId 將填充commentid。

希望你們能有所收穫。CTE 將如下所示:

WITH  Comments
       AS ( SELECT  CommentId , ParentId, CAST(CommentId AS VARBINARY(MAX)) AS Sortkey, 0 AS Indent
            FROM    dbo.Comments
            WHERE   ParentId IS NULL AND PostId = 105
            UNION ALL
            SELECT  b.CommentId , b.ParentId,  c.Sortkey + CAST(b.CommentId AS varbinary(max))  AS Sortkey, c.Indent + 1 AS Indent
            FROM    dbo.Comments b
            INNER JOIN Comments c ON c.CommentId = b.ParentId
          )
  SELECT   *
  FROM     Comments
  ORDER BY Sortkey

樣本輸出

1   NULL    0x0000000000000001  0
5   1   0x00000000000000010000000000000001  1
6   5   0x000000000000000100000000000000010000000000000005  2
2   NULL    0x0000000000000002  0

在 F/B 文章 105 上,有兩條評論(CommentIds 1 和 2)然後有人在 Comment1 上回复(CommentId 5,ParentId 1),然後其他人對該回復發表評論,所以在 Comment5 上(CommentId 6,ParentId 6)

和中提琴,順序是正確的,在文章下,您現在可以按正確的順序顯示評論。為了縮進文章,使其形成和在 facebook 中一樣的輪廓(級別越深,它必須從左邊越多),我還有一個名為 Indent 的列。根是 0,然後在聯合中,我們有 c.Indent + 1 AS Indent 在程式碼中,你現在可以將縮進乘以假設 32px,並以漂亮的層次結構和輪廓顯示註釋。

我認為使用自動增量主鍵 CommentId 作為建構我的 SortKey 的驅動力沒有問題,因為與搞亂以 +1 為種子的數據庫管理鍵相比,搞亂日期(commentdate)會更好

引用自:https://dba.stackexchange.com/questions/43560