2017-08-30 13 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によると、すべての可能なURLの組み合わせを保存。上記の表から

だから、私は次の出力を取得したいのです:私はこのように見て、CTEを書き始めました

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

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が何であるかに従ってURLを保存することです。今はもちろんフォーマットされていませんが、私の出力はフラットなものです:

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

多くの壊れたリンクが作成されます。 再帰的なステップごとにアクション/選択を行う方法はありますか?この問題にはどのように接近すべきですか?

+1

は、あなたのデータ構造は正しいですか?カテゴリの後のURLには特定のものがある前に書籍がありますが、最初の表で説明すると、その関係に基づいてカテゴリに直接移動しますか? – 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 
関連する問題