2013-06-06 37 views
7

Tôi có cấu trúc cây và bảng phân công tiếp theo cho các danh mục khách hàng trong cơ sở dữ liệu máy chủ sql.Tìm tất cả các nút lá bên dưới một cây con trong cấu trúc cây trong máy chủ sql

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

Nếu CustomerCategory có bất kỳ khách hàng nào được chỉ định, chúng tôi không thể thêm một danh mục con khác vào nó. Vì vậy, khách hàng chỉ có thể được thêm vào mức thấp nhất trong mỗi cây con. Nói cách khác, kết quả của truy vấn này

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

sẽ mang lại các nút lá. Điều khác là, cây này có thể có nhiều cấp độ khác nhau, và chúng tôi cũng không muốn giới hạn số lượng các cấp, tuy nhiên, người dùng của chúng tôi sẽ không cần nhiều hơn 10 cấp. Xem xét việc này như một minh hoạ

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 

Yêu cầu của tôi là một cái gì đó như thế này: "Đưa ra một nút trong Categories, Return Tất cả các khách hàng gắn liền với bất kỳ nút dưới nó".

Tôi có thể làm điều đó bằng sql như thế nào? Rõ ràng điều này có thể được thực hiện với một cuộc gọi đệ quy trong mã, nhưng làm thế nào chúng ta có thể làm điều đó trong t-sql (mà không gọi một thủ tục lưu trữ nhiều lần hoặc sử dụng tìm kiếm dựa trên văn bản)?

Bất kỳ cơ thể nào, Sử dụng CTE để giải quyết vấn đề này?

Tôi có một tập hợp kết quả của một cái gì đó như thế này trong tâm trí

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 

này không nhất thiết phải là một ý tưởng tốt để bố trí một kết quả như thế này, này sẽ tiêu tốn quá nhiều không gian, một cái gì đó mà có thể không được yêu cầu, tuy nhiên, tìm kiếm trong tập kết quả như vậy sẽ rất nhanh. Nếu tôi muốn tìm tất cả các khách hàng dưới đây nói categoryId = 2, tôi sẽ chỉ đơn giản là truy vấn

SELECT * FROM resultset where category ID = 2 

Mọi góp ý để cải thiện mô hình dữ liệu được siêu hoan nghênh! Nếu nó giúp giải quyết vấn đề này.

Một lần nữa, tôi không được khắc phục trên tập kết quả này. Bất kỳ Đề xuất nào khác giải quyết vấn đề, "Được cung cấp một nút trong Danh mục, Trả lại Tất cả Khách hàng được đính kèm với bất kỳ nút nào bên dưới", cũng được chấp nhận.

Trả lời

9

Bạn có thể sử dụng một CTE đệ quy xây dựng một bảng chứa tất cả các mối quan hệ cha-con và sử dụng mệnh đề where để có được chỉ là cây con bạn cần (trong ví dụ của tôi, everyting dưới 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 

bạn có thể sửa đổi truy vấn này để thêm bất cứ điều gì bạn cần, ví dụ, để có được khách hàng liên quan đến các hạch loại trong cây con:

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 

và dĩ nhiên bạn có thể tham gia bảng nữa để có được nhãn và thông tin cần thiết khác.

+0

rất thông minh ... rất thông minh ... Cảm ơn. – user1155391

+0

Có cách nào để thực hiện trên máy chủ MS SQL không? – sajushko

Các vấn đề liên quan