具有父子项的分层SQL查询

时间:2016-09-21 11:40:56

标签: mysql sql sql-server postgresql

Category (id, name,        parent_id);
          1   Electronics  NULL
          2   Computers    1
          3   Notebooks    2
          4   Desktops     2

Products (id, name,      category_id);
          1   NotebookX  3
          2   NotebookY  3
          3   NotebookZ  3
          4   DesktopX   2
          5   DesktopY   2

1-我想选择指定类别的父类别列表。

2-我想选择类别和子类别的产品列表。

Select category 1 should return 5 products. 
          1   NotebookX  3
          2   NotebookY  3
          3   NotebookZ  3
          4   DesktopX   2
          5   DesktopY   2
    Select category 2 should return 5 products. 
          1   NotebookX  3
          2   NotebookY  3
          3   NotebookZ  3
          4   DesktopX   2
          5   DesktopY   2
    Select category 3 should return 3 products. 
          1   NotebookX  3
          2   NotebookY  3
          3   NotebookZ  3
    Select category 4 should return 2 products.
          4   DesktopX   2
          5   DesktopY   2

我是sql递归查询的新手,因此无法创建。

WITH RECURSIVE graph AS (
    SELECT id, name
    FROM category
    WHERE parent_id IS NULL
    UNION ALL
    SELECT v.id, v.name
    FROM category as v
    JOIN graph r on v.parent_id = r.id
    ????????????
    ????????????
)
SELECT id, name FROM graph;

(我正在使用postgreql。但你可以编写任何数据库。)

1 个答案:

答案 0 :(得分:1)

试一试( SQL Server 解决方案):

DECLARE @category int = 3

;WITH rec AS (
SELECT *
FROM Category c
WHERE c.id = @category
UNION ALL
SELECT c.*
FROM rec r
INNER JOIN Category c
    ON c.parent_id = r.id
)

SELECT p.*
FROM Products p
INNER JOIN rec r
    ON r.id = p.category_id

首先我们得到一个我们选择的类别。比我们在递归部分中从Category所有孩子中选择。之后我们进入rec所有子类别。我们加入Productsrec的类别。

修改#1

您可以将rec结果放入临时表中,然后使用它们:

SELECT *
INTO #rec
FROM rec

SELECT p.*
FROM Products p
INNER JOIN #rec r
    ON r.id = p.category_id

SELECT *
FROM #rec

DROP TABLE #rec

@category=3的输出:

id          name      category_id
----------- --------- -----------
1           NotebookX 3
2           NotebookY 3
3           NotebookZ 3

(3 row(s) affected)

id          name        parent_id
----------- ----------- -----------
3           Notebooks   2

(1 row(s) affected)

修改#2

获得后代:

DECLARE @category int = 2

;WITH rec AS (
SELECT *
FROM Category c
WHERE c.id = @category
UNION ALL
SELECT c.*
FROM rec r
INNER JOIN Category c
    ON c.id = r.parent_id
)

SELECT *
FROM rec

输出:

id  name        parent_id
2   Computers   1
1   Electronics NULL

对于父母:

DECLARE @category int = 2

;WITH rec AS (
SELECT *
FROM Category c
WHERE c.id = @category
UNION ALL
SELECT c.*
FROM rec r
INNER JOIN Category c
    ON c.parent_id = r.id
)

输出:

id  name        parent_id
2   Computers   1
3   Notebooks   2
4   Desktops    2