0

親と子のカテゴリの関係をソトレスする標準テーブルがあります...このように。

id, parent, catName, sort

そして、次のクエリを使用して再帰ツリーを作成します

;WITH cte AS (
    SELECT 0 AS lvl, id, catName, parent,levels,sort,
        CAST(id AS VARCHAR(128)) AS path
    FROM CategoriesMap WHERE parent =0
    UNION ALL
    SELECT p.lvl + 1, c.id, c.catName, c.parent,c.levels,c.sort,
        CAST(p.path + '_' + CAST(c.id AS VARCHAR) AS VARCHAR(128))
    FROM CategoriesMap c
    INNER JOIN cte p ON p.id = c.parent
)
SELECT 
    id, 
    catName AS catName, 
    lvl,
    levels,
    path,
    parent,
    sort
FROM cte 
ORDER BY path

そして、出力は次のようになります。

ここに画像の説明を入力してください

値がASP.NETおよびCLASSICASPの行を探します。これらは、テクノロジ>ソフトウェア(親)の最後のリーフ(子)です。任意の親(最後の親)の最後の子を並べ替えます。特定のノード(最後の子)に対して複数の親を持つことができます。気になるのは、[並べ替え]列を使用して最後の子(リーフ)を並べ替えることだけです。

したがって、基本的に「Classic Asp」は、「Asp.Net」の前に配置する必要があります(最後の列は私の画像のSORT列です)。

私のクエリは問題なく、期待どおりの結果を返します...唯一の課題は、テーブルのSORT列を使用して最後のノードをSORTしたいことです。最後のノードには、並べ替える3つまたは4つの子を含めることができ、最後の上のすべてのノードを並べ替えることができます。ノードはその親です(すでに正しい順序になっています)。

このような出力が必要です...インターネット>ISP>CableVision(1):Verizon(2)ご覧のとおり、CableVisionとVerizonのソート値は1、次に2です。ここで、ショッピング>クーポン> Macys(0 ):シアーズ(2)、同じこと.... Macys&Searsを並べ替えてほしい...そして、両親がショッピング>クーポンであることは明らかです。

@Richard別名cyberkiwi、コードを適用した後、Categoriesテーブルの並べ替えは非常にランダムです。出力は以下です ここに画像の説明を入力してください

4

2 に答える 2

1

このSQLFiddleは、必要なものを提供するはずです。秘訣は、葉と枝を混ぜるときです。私の解決策では、葉は常に枝の前に表示され、葉の中で(枝と混合されている場合でも)、sortもちろん列で並べ替えられます。

DDL

create table CategoriesMap(
    id int, parent int, catname varchar(20), sort int);
insert CategoriesMap select
    1, 0, 'Activities', null union all select
    2, 0, 'Property', null union all select
    3, 2, 'For rent', null union all select
    4, 2, 'For sale', null union all select
    12, 0, 'Technology', 3 union all select
    15, 12, 'Hardware', null union all select
    21, 12, 'Phones', null union all select
    22, 15, 'Computers', null union all select
    18, 12, 'Software', null union all select
    19, 18, 'Asp.net', 2 union all select
    20, 18, 'SQL', 3 union all select
    23, 18, 'Php', 4 union all select
    24, 18, 'Classic ASP', 1;

クエリ

;WITH leaves AS (
    SELECT A.id
      FROM CategoriesMap A
 LEFT JOIN CategoriesMap B ON A.id=B.parent
     WHERE B.id is null
)
,cte AS (
    SELECT 0 AS lvl, id, catName, parent,sort,
           CAST(id AS VARCHAR(MAX)) AS path,
           '/'+CAST(id AS VARCHAR(MAX))+'/' AS hier
      FROM CategoriesMap
     WHERE parent =0
 UNION ALL
    SELECT p.lvl + 1, c.id, c.catName, c.parent,c.sort,
           p.path + '_' + CAST(c.id AS VARCHAR(MAX)),
           p.hier + CAST(c.id AS VARCHAR(MAX)) + '/'
      FROM CategoriesMap c
      JOIN cte p ON p.id = c.parent
)
    SELECT c.id,
           c.catName,
           c.lvl,
           --levels,
           c.path,
           --c.hier,
           c.parent,
           c.sort
      FROM cte c
 LEFT JOIN leaves l on l.id=c.id
  ORDER BY CASE WHEN l.id is null
                then cast(hier as hierarchyid)
                else cast(hier as hierarchyid).GetAncestor(1)
                END,
           CASE WHEN l.id is null then 0 else 1 end,
           sort
于 2012-09-24T08:17:13.493 に答える
1

の計算pathを1レベル遅らせることで、最終結果セットに親パス(ppath)が使用可能になります。

;WITH cte AS (
    SELECT 0 AS lvl, id, catName, parent,levels,sort,
        CAST('' AS VARCHAR(128)) AS ppath
    FROM CategoriesMap WHERE parent =0
    UNION ALL
    SELECT p.lvl + 1, c.id, c.catName, c.parent,c.levels,c.sort,
        CAST(p.ppath + '_' + CAST(p.id AS VARCHAR) AS VARCHAR(128))
    FROM CategoriesMap c
    INNER JOIN cte p ON p.id = c.parent
)
SELECT 
    id, 
    catName, 
    lvl,
    levels,
    CAST(ppath + '_' + CAST(id AS VARCHAR) AS VARCHAR(128)) AS path,
    parent,
    sort
FROM cte
ORDER BY 
    CASE WHEN sort IS NULL
           THEN path
           ELSE ppath
    END
  , sort ;

上記でエラーが発生する理由はよくわかりません。これはしません:

ORDER BY 
    CASE WHEN sort IS NULL
      THEN CAST(ppath + '_' + CAST(id AS VARCHAR) AS VARCHAR(128))
      ELSE ppath
    END
  , sort ;
于 2012-09-24T08:19:50.720 に答える