Mysql 具有父子项的分层SQL查询

Mysql 具有父子项的分层SQL查询,mysql,sql,sql-server,postgresql,Mysql,Sql,Sql Server,Postgresql,1-我要选择指定类别的父类别列表 2-我想选择类别和子类别的产品列表 Category (id, name, parent_id); 1 Electronics NULL 2 Computers 1 3 Notebooks 2 4 Desktops 2 Products (id, name, category_id); 1 Not

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

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

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
我不熟悉sql递归查询,因此无法创建

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
我正在使用postgreql。但是您可以编写任何数据库。

尝试一下SQL Server解决方案:

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;
首先,我们得到一个我们选择的类别。然后我们从类别中选择递归部分中的所有子类别。在那之后,我们进入了rec的所有子类别。然后我们加入rec的产品类别

编辑1

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

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=3的输出:

编辑2

要获取后代,请执行以下操作:

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)
输出:

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
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
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.id = r.parent_id
)

SELECT *
FROM rec
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
)

这很好,但如何列出类别的父级和子级?将“上次选择”更改为“从记录中选择*”,它将列出您选择的类别及其子级。我展开回答。请看一看。我只想列出某一类别的家长,而不是产品。计算机类别的示例有1个parentsElectronics和2个子代笔记本电脑、台式机。我需要为这些列表创建两个sql查询。其中一个将列出子类,另一个将列出某个类别的父类。好吧,这不是你在问题中写的。。。F.e.选择类别1应返回5种产品…-我示例中的第一个查询就是这样做的。如果您需要在两个单独的列表中获取父级和子级-您可以使用相同的查询,但使用ON c.id=r.parent\u id来显示所选类别的父级。我将此添加到我的答案中,请参见第2版