仅显示包含产品的类别

时间:2016-06-07 14:39:59

标签: sql sql-server sql-server-2012 recursive-query

原谅糟糕的头衔,但我找不到用抽象的术语表达我想要的东西的好方法。

无论如何我有3张桌子

tbl_product:

PID | productname
1   | product 1
2   | product 2
3   | product 3
4   | product 4
..

tbl_categories,motherCategory允许我嵌套类别:

CID | categoriename    | motherCategory
1   | electronics      | NULL
2   | clothing         | NULL
3   | Arduino          | 1
4   | Casings, extra's | 3
..

tbl_productInCategory PID和CID分别是tbl_product和tbl_categories中PID和CID的外键。产品可以分配多个类别,因此PID可以在此表中多次出现。

PID | CID
1   | 1
2   | 1
3   | 3
4   | 4

现在我有一个查询,如果我给出mothercategory,则返回所有类别。 我想要做的是只显示递归中包含产品的类别。

例如上面的示例数据我显示所有类别(motherCategory为null),我希望它只返回电子产品,因为没有产品类别2,衣服。

然而,我遇到的问题是我还希望这个递归工作。考虑一下这个tbl_productInCategory:

PID | CID
1   | 2
2   | 2
3   | 2
4   | 4

现在它应该返回服装和电子产品,即使电子产品中没有产品,因为有嵌套类别的产品arduino->外壳,外壳。如果我用motherCategory显示所有类别,电子产品它也应该返回arduino。

我无法弄清楚如何做到这一点,任何帮助或指针都表示赞赏。

3 个答案:

答案 0 :(得分:3)

首先,您应该选择存在产品的所有类别。在接下来的步骤中选择母类别。

WITH CTE AS
(
SELECT tbl_categories.*
FROM
tbl_categories
JOIN tbl_productInCategory on tbl_productInCategory.CID = tbl_categories.CID

UNION ALL 

SELECT tbl_categories.*
FROM tbl_categories 
JOIN CTE on tbl_categories.CID = CTE.motherCategory 
)
SELECT DISTINCT * FROM CTE

答案 1 :(得分:0)

使用递归CTE获取类别树的派生表,然后将其连接到您的ProductCategory表。

答案 2 :(得分:0)

这不是我以前做过的事情,但是一些谷歌搜索表明它是可能的。

https://technet.microsoft.com/en-us/library/ms186243(v=sql.105).aspx

  

递归执行的语义如下:   将CTE表达式拆分为锚点和递归成员。   运行创建第一个调用或基本结果集(T0)的锚成员。   以Ti作为输入并以Ti + 1作为输出运行递归成员。   重复步骤3,直到返回空集。   返回结果集。这是T0到Tn的UNION ALL。

USE AdventureWorks2008R2;
GO
WITH DirectReports (ManagerID, EmployeeID, Title, DeptID, Level)
AS
(
-- Anchor member definition
    SELECT e.ManagerID, e.EmployeeID, e.Title, edh.DepartmentID, 
        0 AS Level
    FROM dbo.MyEmployees AS e
    INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh
        ON e.EmployeeID = edh.BusinessEntityID AND edh.EndDate IS NULL
    WHERE ManagerID IS NULL
    UNION ALL
-- Recursive member definition
    SELECT e.ManagerID, e.EmployeeID, e.Title, edh.DepartmentID,
        Level + 1
    FROM dbo.MyEmployees AS e
    INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh
        ON e.EmployeeID = edh.BusinessEntityID AND edh.EndDate IS NULL
    INNER JOIN DirectReports AS d
        ON e.ManagerID = d.EmployeeID
)
-- Statement that executes the CTE
SELECT ManagerID, EmployeeID, Title, DeptID, Level
FROM DirectReports
INNER JOIN HumanResources.Department AS dp
    ON DirectReports.DeptID = dp.DepartmentID
WHERE dp.GroupName = N'Sales and Marketing' OR Level = 0;
GO