use*_*391 8 t-sql tree sql-server-2008
我有一个树结构,以及随后的sql server数据库中客户类别的分配表.
CustomerCategory (CategoryID, ParentId)
CustomerInCategory(CustomerID, CategoryID)
Run Code Online (Sandbox Code Playgroud)
如果CustomerCategory已为其分配了任何客户,则我们无法向其添加其他子类别.因此,客户只能添加到每个子树中的最低级别.在其他意义上,这个查询的结果
SELECT * FROM `CustomerCategory` WHERE `CategoryId` NOT IN
(SELECT DISTINCT `parentid` FROM `CustomerCategory` WHERE `parentid` IS NOT NULL)
Run Code Online (Sandbox Code Playgroud)
会产生叶节点.另一方面,这棵树可能有不同级别的子树,而且我们也不想以任何方式限制级别数,但是,我们的用户不需要超过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
Run Code Online (Sandbox Code Playgroud)
我的要求是这样的,"给定类别中的节点,将所有客户连接到它下面的任何节点".
我怎么能用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
Run Code Online (Sandbox Code Playgroud)
布置这样的结果不一定是个好主意,这会消耗太多空间,这可能不需要,但是,在这样的结果集中搜索会非常快.如果我想找到以下所有客户说categoryId = 2,我只想查询
SELECT * FROM resultset where category ID = 2
Run Code Online (Sandbox Code Playgroud)
任何改进数据模型的建议都是非常受欢迎的!如果它有助于解决这个问题.
再一次,我并不关注这个结果集.解决问题的任何其他建议,"给定类别中的节点,返回附加到其下任何节点的所有客户",被广泛接受.
Xav*_*r G 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
Run Code Online (Sandbox Code Playgroud)
您可以修改此查询以添加所需的任何内容,例如,将客户链接到子树中的类别节点:
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
Run Code Online (Sandbox Code Playgroud)
当然,您可以加入更多表格以获取标签和其他所需信息.