8

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

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

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

再一次,我不关注这个结果集。任何其他解决问题的建议,“给定类别中的一个节点,返回所有附加到它下面的任何节点的客户”,都被很好地接受了。

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 回答