2017-08-30 54 views
1

我有一個數據庫表,它使用嵌套的URL構造,使用ParentID和ID來告訴URL的哪一部分屬於哪裏。從數據庫中遞歸地獲取嵌套的URL

表結構如下:

+-----+----------+------------+-------------+ 
| ID | ParentID | Name |  Url | 
+-----+----------+------------+-------------+ 
| 1 |  0 | Categories | categories | 
| 34 |  1 | Movies  | movies  | 
| 281 |  34 | Star Wars | star-wars | 
| 33 |  1 | Books  | a-good-book | 
+-----+----------+------------+-------------+ 

我想要做的是,我希望能夠以遞歸遍歷所有的字段,並根據PARENTID,保存所有可能的地址組合。

所以,從上面的表,我想獲得以下輸出:

mysite.com/categories 
mysite.com/categories/movies 
mysite.com/categories/movies/star-wars 
mysite.com/categories/books 
mysite.com/categories/books/a-good-book 

我已經開始寫CTE,看起來像這樣:

WITH CategoriesCTE AS 
    (
    SELECT 
     Name, 
     Url, 
     ParentID, 
     ID 
    FROM myDB 
    WHERE ParentID = 1 

    UNION ALL 

    SELECT 
     a.Name, 
     a.Url, 
     a.ParentID, 
     a.ID 
    FROM myDB.a 
    INNER JOIN CategoriesCTE s on a.ParentID = s.ID 
) 

    SELECT * FROM CategoriesCTE 

事情是,這個數據庫調用保存了一切。我必須做的是,爲每一步,保存所有的URL,然後爲每個ID,根據ParentID是什麼保存網址。現在,它當然沒有被格式化,但我的輸出是斷然一樣的東西:

mysite.com/categories 
mysite.com/movies 
mysite.com/star-wars 
mysite.com/a-good-book 

它創建了一個很多損壞的鏈接。 是否有某種方式爲每個遞歸步驟執行操作/選擇?我應該如何解決這個問題?

+1

是您的數據結構是否正確?類別之後的網址具有書籍,但在它具有特定的內容之前,但是在您描述的第一張表格中,基於這種關係,它會直接轉到類別上? – Leonidas199x

回答

0

看看你覺得這...

IF OBJECT_ID('tempdb..#SomeTable', 'U') IS NOT NULL 
DROP TABLE #SomeTable; 

CREATE TABLE #SomeTable (
    ID INT NOT NULL, 
    ParentID INT NOT NULL, 
    FolderName VARCHAR(20) NOT NULL, 
    UrlPath VARCHAR(8000) NULL 
    ); 
INSERT #SomeTable (ID, ParentID, FolderName) VALUES 
    (1 , 0 , 'categories'), 
    (34 , 1 , 'movies'), 
    (281, 34, 'star-wars'), 
    (33 , 1 , 'a-good-book'); 

-- SELECT * FROM #SomeTable st; 

WITH 
    cte_Categories AS (
     SELECT 
      SitePath = CAST(CONCAT('mysite.com/', st.FolderName) AS VARCHAR(8000)), 
      st.ID, 
      NodeLevel = 1 
     FROM 
      #SomeTable st 
     WHERE 
      st.ParentID = 0 
     UNION ALL 
     SELECT 
      SitePath = CAST(CONCAT(c.SitePath, '/', st.FolderName) AS VARCHAR(8000)), 
      st.ID, 
      nodeLevel = c.NodeLevel + 1 
     FROM 
      cte_Categories c 
      JOIN #SomeTable st 
       ON c.ID = st.ParentID 
     ) 
SELECT 
    c.SitePath, 
    c.ID, 
    c.NodeLevel 
FROM 
    cte_Categories c; 
1

添加了一些新的領域,以你的遞歸CTE追蹤:

  1. 遞歸的深度(這樣你就可以找到具有最大深度
  2. 將通過每次迭代通過內置的路徑記錄串聯的最新值給它。
  3. 遞歸的出發點,所以你知道你開始

什麼紀錄
WITH CategoriesCTE AS 
    (
    SELECT Name, Url, ParentID, ID, 1 as depth, CAST(url as VARCHAR(500)) as path, url as startingpoint 
    FROM myDB 
    WHERE ParentID = 1 
    UNION ALL 

    SELECT a.Name, a.Url, a.ParentID, a.ID, s.depth + 1, a.url + s.path, s.url 
    FROM myDB.a 
    INNER JOIN CategoriesCTE s on a.ParentID = s.ID 
) 

    SELECT * FROM CategoriesCTE