2010-12-03 116 views
3

我有3个表:如何获取每个产品所属的所有父级和子级类别?

CREATE TABLE [dbo].[ProductCategory](
[categoryID] [int] IDENTITY(1,1) NOT NULL, 
[categoryParentID] [int] NULL, 
[categoryName] [nvarchar](200) NOT NULL 
) 

CREATE TABLE [dbo].[Product] 
(
[productID] [bigint] IDENTITY(1,1) NOT NULL, 
[productName] [nvarchar(100)] NOT NULL, 
. 
. 
) 

CREATE TABLE [dbo].[ProductToCategoryLink] 
(
[productID] [bigint] NOT NULL, 
[categoryID] [int] NOT NULL 
) 

样本数据例如:

产品:

1, 'Book_1';

2,'Book_2';

产品分类:

1,NULL, '图书';

2,1,'Books Subcategory lvl_1';

3,2,'Books Subcategory lvl_2';

4,3,'Books Subcategory lvl_3';

ProductToCategoryLink:

1,4;

2,2;

问题:如何获取每个产品所属的所有父级和子级类别?

所以,我需要得到的东西是这样的:


的productID,产品名称,的categoryID,类别名称

1, 'Book_1',1, '图书';

1,'Book_1',2,'Books Subcategory lvl_1';

1,'Book_1',3,'Books Subcategory lvl_2';

1,'Book_1',4,'Books Subcategory lvl_3';

2,'Book_2',1,'Books';

2,'Book_2',2,'Books Subcategory lvl_1';

回答

1

在这篇文章的底部显示的SQL查询应该做的,如果详细。

关键特性是层次结构表表达式的递归定义。第一个SELECT检索所有产品类别链接及其名称和类别父ID。这是递归的基本情况。第二个SELECT查找上一步中找到的所有行的所有类别父行。特别要注意的是,第二个SELECT再次加入层次结构表达式,使查询递归。 SQL Server将重复评估第二个SELECT,直到找不到新记录。第三个SELECT语句只是返回结果。

正如您所预料的那样,如果类别父链中有循环,那将是一件坏事。 SQL Server会限制它在放弃查询之前执行的次数。默认限制是100,这可能就足够了,除非类别层次非常深。如有必要,可以使用MAXRECURSION查询选项将其提高到32767。

下面是SQL查询:

WITH 
    hierarchy AS (
    SELECT 
     prod.productId 
    , prod.productName 
    , cat.categoryId 
    , cat.categoryParentId 
    , cat.categoryName 
    FROM dbo.ProductToCategoryLink AS link 
    INNER JOIN dbo.Product AS prod 
     ON prod.productId = link.productId 
    INNER JOIN dbo.ProductCategory AS cat 
     ON cat.categoryId = link.categoryId 
    UNION ALL 
    SELECT 
     child.productId 
    , child.productName 
    , parent.categoryId 
    , parent.categoryParentId 
    , parent.categoryName 
    FROM hierarchy AS child 
    INNER JOIN dbo.ProductCategory AS parent 
     ON parent.categoryId = child.categoryParentId 
) 
SELECT 
    productId 
, productName 
, categoryId 
, categoryName 
FROM hierarchy 
ORDER BY 
    productId 
, categoryId 
3

最简单的方法是通过公共表格表达式。 >Link<

使用直接链接作为锚点,然后展开两次:首先展开找到的锚点的父母,然后用第二个联合展开子类。

+0

非常酷的,从来没有听说过的CTE之前。这将会在一些旧的项目中派上用场:) – CodeMonkey1313 2010-12-03 12:13:37

相关问题