了解递归 CTE 中的内连接 (MySQL)

问题描述 投票:0回答:1

以下代码来自:https://www.freecodecamp.org/news/mysql-common-table-expressions/

数据:

CREATE TABLE
categories (
    id int,
    cat_name varchar(100),
    parent_category_id int DEFAULT NULL
);

INSERT INTO
    categories
VALUES
    (1, 'Mens', NULL),
    (2, 'Tops', 1),
    (3, 'Jerseys', 2),
    (4, 'England', 3);

代码:

WITH RECURSIVE
category_tree AS (
    SELECT
        id,
        cat_name,
        parent_category_id,
        cat_name AS full_name
    FROM categories
    WHERE parent_category_id IS NULL                
    UNION ALL                                       
    SELECT
        c.id,                                       
        c.cat_name,                                 
        c.parent_category_id,
        CONCAT (ct.full_name, ' > ', c.cat_name)
    FROM categories c
        JOIN category_tree ct 
        ON c.parent_category_id = ct.id             
)
SELECT
    id, full_name
FROM
    category_tree;
categories:
| id | cat_name | parent_category_id |
| ---| ---------| -------------------|
| 1  | Mens     | NULL               |
| 2  | Tops     | 1                  |
| 3  | Jerseys  | 2                  | 
| 4  | England  | 3                  |

category_tree: 
| id | full_name                       |
| ---| ------------------------------- |
| 1  | Mens                            |
| 2  | Mens > Tops                     |
| 3  | Mens > Tops > Jerseys           |
| 4  | Mens > Tops > Jerseys > England |
  • 我无法理解这句话:
    ON c.parent_category_id = ct.id
  • 根据我的理解,ct.id 将始终返回 id: 1 和 cat_name: 'Mens'。
  • category_tree CTE 不应该停在“Mens > Tops”吗?

如果有任何详细的解释,我将不胜感激。非常感谢。

mysql inner-join common-table-expression recursive-cte
1个回答
0
投票

参见示例 您的数据(来源) |编号 |猫名 |父类别 ID | |---:|:---------|--------------------:| | 1 |男装 | | | 2 |上衣 | 1 | | 3 |球衣 | 2 | | 4 |英格兰-1 | 3 | | 5 |英格兰-2 | 3 |

以及递归查询

WITH RECURSIVE category_tree AS (
   SELECT 0 as lvl, id, cat_name, parent_category_id,
      cat_name AS full_name
   FROM categories
   WHERE parent_category_id IS NULL                
   UNION ALL                                       
   SELECT lvl+1 as lvl,c.id, c.cat_name,c.parent_category_id,
      CONCAT (ct.full_name, ' > ', c.cat_name)
   FROM category_tree ct 
   INNER JOIN categories c
            ON c.parent_category_id = ct.id             
    )
SELECT * 
FROM category_tree;
lvl id 猫名 父类别_id 全名
0 1 男士 男士
1 2 上衣 1 男士 > 上衣
2 3 球衣 2 男士 > 上衣 > 球衣
3 4 英格兰-1 3 男装 > 上衣 > 球衣 > England-1
3 5 英格兰-2 3 男装 > 上衣 > 球衣 > England-2

让我们一步步看一下请求。 我将添加列 lvl 以进行步骤编号。

  1. 第一步是执行查询的
    anchor
    部分
   SELECT 0 as lvl, id, cat_name, parent_category_id,
      cat_name AS full_name
   FROM categories
   WHERE parent_category_id IS NULL                

输出是

lvl id 猫名 父类别_id 全名
0 1 男士 男士
  1. 第二步 - 将上面的结果与源连接(内部)
   SELECT lvl+1 as lvl,c.id, c.cat_name,c.parent_category_id,
      CONCAT (ct.full_name, ' > ', c.cat_name)
   FROM category_tree ct 
   INNER JOIN categories c
            ON c.parent_category_id = ct.id             

这部分输出是

lvl id 猫名 父类别_id 全名
1 2 上衣 1 男士 > 上衣

3.与

anchor
并集结果为 |等级 |编号 |猫名 |父类别 ID |全名 | |----:|---:|:---------|--------------------:|:----- -----| | 0 | 1 |男装 | |男装 | | 1 | 2 |上衣 | 1 |男装 > 上衣 |

4.下一步 - 查询的递归部分 - 将步骤 3 结果与源连接

WITH RECURSIVE category_tree AS (
   SELECT 0 as lvl, id, cat_name, parent_category_id,
      cat_name AS full_name
   FROM categories
   WHERE parent_category_id IS NULL                
   UNION ALL                                       
   SELECT lvl+1 as lvl,c.id, c.cat_name,c.parent_category_id,
      CONCAT (ct.full_name, ' > ', c.cat_name)
   FROM category_tree ct 
   INNER JOIN categories c
            ON c.parent_category_id = ct.id             
    )

我们加入(内部)

lvl id 猫名 父类别_id 全名
0 1 男士 男士
1 2 上衣 1 男士 > 上衣

带有源表。

JOIN 结果是

lvl id 猫名 父类别_id 全名
2 3 球衣 2 男士 > 上衣 > 球衣

UNION ALL 之后

"� 749c ��
lvl id 猫名 父类别_id 全名
0 1 男士 男士
1 2 上衣 1 男士 > 上衣
2 3 球衣 2 男士 > 上衣 > 球衣
\n"
    下一步 - 将上面的输出与源连接(内部) JOIN 输出是
lvlid猫名父类别_id全名34英格兰-13男装 > 上衣 > 球衣 > England-135英格兰-23男装 > 上衣 > 球衣 > England-2
UNION ALL 之后 |等级 |编号 |猫名 |父类别 ID |全名 | |----:|---:|:---------|--------------------:|:----- -----| | 0 | 1 |男装 |

|男装 | | 1 | 2 |上衣 | 1 |男装 > 上衣 | | 2 | 3 |球衣 | 2 |男装 > 上衣 > 球衣 | | 3 | 4 |英格兰-1 | 3 |男装 > 上衣 > 球衣 > England-1 | 男装 | 3 | 5 |英格兰-2 | 3 |男装 > 上衣 > 球衣 > England-2 |

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.