8

私はツリー構造と、それに続く顧客カテゴリの割り当てテーブルを SQL Server データベースに作成しました。

CustomerCategory (CategoryID, ParentId)
CustomerInCategory(CustomerID, CategoryID)

CustomerCategory に顧客が割り当てられている場合、別のサブカテゴリを追加することはできません。したがって、Customer はすべてのサブ ツリーの最下位レベルにのみ追加できます。言い換えれば、このクエリの結果

SELECT * FROM `CustomerCategory` WHERE `CategoryId` NOT IN 
(SELECT DISTINCT `parentid` FROM `CustomerCategory` WHERE `parentid` IS NOT NULL)

葉ノードを生成します。もう 1 つのことは、このツリーにはさまざまなレベルのサブツリーが含まれる可能性があることです。また、いずれにせよ、レベルの数を制限したくありませんが、ユーザーは 10 を超えるレベルを必要としません。これは例として考えてください

CategoryID------ParentID---------------Name
1               NULL                   All Customers
2               1                      Domestic
3               1                      International
4               2                      Independent Retailers
5               2                      Chain Retailers
6               2                      Whole Sellers
7               5                      A-Mart
8               5                      B-Mart
9               4                      Grocery Stores
10              4                      Restaurants
11              4                      Cafes

CustomerID---------CustomerName----------Category
1                  Int.Customer#1               3
2                  Int.Customer#2               3
3                  A-Mart.Branch#1              7
4                  A-Mart.Branch#2              7
5                  B-Mart.Branch#1              8
6                  B-Mart.Branch#2              8
7                  Grocery#1                    9
8                  Grocery#2                    9
9                  Grocery#3                    9
10                 Restaurant#1                 10
11                 Restaurant#2                 10
12                 Cafe#1                       11
13                 Wholeseller#1                6
14                 Wholeseller#2                6

私の要件は、「カテゴリのノードが与えられた場合、その下のノードに接続されているすべての顧客を返す」のようなものです。

どうすればSQLでそれを行うことができますか?

明らかに、これはコード内の再帰呼び出しで実行できますが、t-sql で (ストアド プロシージャを何度も呼び出したり、テキスト ベースの検索を使用したりせずに) どのように実行できるでしょうか?

CTE を使用してこの問題を解決できる団体はありますか?

私はこのようなものの結果セットを念頭に置いています

CustomerID--------Customer Name----------------CategoryId----------CAtegoryName

12                Cafe#1                       11                  Cafes
12                Cafe#1                       4                   IndependentRetailers
12                Cafe#1                       2                   Demoestic
12                Cafe#1                       1                   AllCustomers
.
.
.
4                 A-Mart.Branch#2              7                  A-Mart
4                 A-Mart.Branch#2              5                  Chain Retailers
4                 A-Mart.Branch#2              2                  Domestic
4                 A-Mart.Branch#2              1                  All Customers
.
.
.
14                 Wholeseller#2               6                  WholeSellers
14                 Wholeseller#2               2                  Domestic
14                 Wholeseller#2               1                  All Customers

このような結果をレイアウトすることは、必ずしも良い考えではありません。必要ではないかもしれませんが、スペースを消費しすぎますが、そのような結果セットでの検索は非常に高速です。以下のすべての顧客が categoryId = 2 と言う場合は、単純にクエリを実行します。

SELECT * FROM resultset where category ID = 2

データモデルを改善するための提案は大歓迎です! この問題の解決に役立つ場合。

繰り返しますが、私はこの結果セットに固執していません。問題を解決する他の提案、「カテゴリ内のノードが与えられた場合、その下の任意のノードに接続されているすべての顧客を返す」は、よく受け入れられます。

4

1 に答える 1

10

CTE を使用して、すべての親子関係を含むテーブルを再帰的に構築し、where 句を使用して必要なサブツリーのみを取得できます (私の例では、CategoryId 5 の下にあるすべて)。

WITH CategorySubTree AS (
    SELECT cc.CategoryId as SubTreeRoot,
            cc.CategoryId 
            FROM CustomerCategory cc
UNION ALL
    SELECT cst.SubTreeRoot, cc.CategoryId
        FROM CustomerCategory cc
        INNER JOIN CategorySubTree cst ON cst.CategoryId = cc.parentId
)
SELECT cst.CategoryId
FROM CategorySubTree cst
WHERE cst.SubTreeRoot = 5

このクエリを変更して、必要なものを追加できます。たとえば、顧客をサブツリーのカテゴリ ノードにリンクさせることができます。

WITH CategorySubTree AS (
    SELECT cc.CategoryId as SubTreeRoot,
            cc.CategoryId 
            FROM CustomerCategory cc
UNION ALL
    SELECT cst.SubTreeRoot, cc.CategoryId
        FROM CustomerCategory cc
        INNER JOIN CategorySubTree cst ON cst.CategoryId = cc.parentId
)
SELECT cst.CategoryId,cic.CustomerId
FROM CategorySubTree cst
        INNER JOIN CustomerInCategory cic ON cic.CategoryId = cst.CategoryId
WHERE cst.SubTreeRoot = 5

もちろん、さらにテーブルを結合して、ラベルやその他の必要な情報を取得することもできます。

于 2013-06-06T15:28:51.373 に答える