在sql server中的树结构中查找子树下的所有叶节点 [英] Find all the leaf nodes below a subtree in a Tree structure in sql server

查看:60
本文介绍了在sql server中的树结构中查找子树下的所有叶节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个树结构,以及它在 sql server 数据库中的客户类别的后续分配表.

I've a tree structure, and its subsequent assignment table for customer categories in an sql server database.

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

如果一个 CustomerCategory 有任何客户分配给它,我们不能向它添加另一个子类别.因此,Customer 只能添加到每个子树中的最低级别.换句话说,这个查询的结果

If a CustomerCategory has any customer assigned to it, we can't add another subcategory to it. So, Customer can only be added to the lowest level in every sub tree. In other sense, the result of this query

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

将产生叶节点.另一件事是,这棵树可能有不同级别的子树,我们也不想限制级别的数量,但是,我们的用户不会需要超过 10 个级别.将此视为说明

would yield leaf nodes. The Other thing is that, this tree might have subtrees of different levels, and we also, don't want to bound the number of levels in anyway, however, our users won't need more than 10 levels. Consider this as an illustration

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

我的要求是这样的,给定类别中的一个节点,返回附加到其下任何节点的所有客户".

My requirement is something like this, "Given a node in Categories, Return All the Customers attached to any node below it".

我怎样才能用 sql 做到这一点?

How can I do it with sql?

显然这可以通过代码中的递归调用来完成,但是我们如何在 t-sql 中做到这一点(无需多次调用存储过程或使用基于文本的搜索)?

Obviously this can be done with a recursive call in the code, but how can we do it in t-sql (without calling a stored procedure several times or using text-based search)?

任何机构都可以使用 CTE 来解决这个问题吗?

Can any body, Use a CTE to solve this problem?

我有一个类似这样的结果集

I have a result set of something like this in mind

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 ,我会简单地查询

This is not necessarily a good Idea to layout a result like this, This would consume too much space, something that might not be required, yet, a search in such result set would be very fast. If I want to find all the customers below say categoryId = 2 , I would simply query

SELECT * FROM resultset where category ID = 2

非常欢迎任何改进数据模型的建议!如果它有助于解决这个问题.

Any suggestions to improve the data model is super welcomed! If It helps solving this problem.

再一次,我并不关注这个结果集.任何其他解决问题的建议,给定类别中的一个节点,返回附加到其下任何节点的所有客户",这是公认的.

Once again, I'm not fixated on this result set. Any other Suggestion that solves the problem, "Given a node in Categories, Return All the Customers attached to any node below it", is well accepted.

推荐答案

您可以使用 CTE 递归构建包含所有父子关系的表,并使用 where 子句仅获取您需要的子树(在我的示例中), 一切都在 CategoryId 下 5) :

You can use a CTE to recursively build a table containing all the parent-child relationships and use the where clause to get only the subtree you need (in my example, everyting under 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

您可以修改此查询以添加您需要的任何内容,例如,将客户链接到子树中的类别节点:

You can modify this query to add whatever you need, for example, to get customers linked to the category nodes in the subtree :

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

当然,您可以加入更多表格以获取标签和其他所需信息.

And of course you can join further tables to get labels and other needed information.

这篇关于在sql server中的树结构中查找子树下的所有叶节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆