2013-06-06 46 views
7

我有一個樹結構及其在SQL Server數據庫中的客戶類別的後續分配表。在sql服務器中的樹結構中查找子樹下面的所有葉節點

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

如果某個CustomerCategory有任何客戶分配給它,我們不能爲其添加另一個子類別。因此,只能將客戶添加到每個子樹中的最低級別。換句話說,這個查詢的結果是

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

會產生葉節點。另一件事是,這棵樹可能有不同級別的子樹,我們也不想限制級別的數量,但是,我們的用戶不需要超過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 

任何建議,以提高數據模型是超級歡迎!如果它有助於解決這個問題。

再一次,我沒有關注這個結果集。任何其他解決此問題的建議, 「給定類別中的節點,將所有客戶連接到它下面的任何節點」,都被廣泛接受。

回答

9

可以使用CTE遞歸構建包含所有的父子關係的表,並使用where子句只得到你需要(在我的例子下的CategoryId 5,everyting)子樹:

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 

當然,您也可以加入進一步的表來獲得標籤和其他所需信息。

+0

很聰明......很聰明......謝謝。 – user1155391

+0

有沒有辦法在MS SQL服務器上做到這一點? – sajushko