以下代码来自: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
如果有任何详细的解释,我将不胜感激。非常感谢。
参见示例 您的数据(来源) |编号 |猫名 |父类别 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 以进行步骤编号。
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 | 男士 | 空 | 男士 |
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 之后
lvl | id | 猫名 | 父类别_id | 全名 |
---|---|---|---|---|
0 | 1 | 男士 | 空 | 男士 |
1 | 2 | 上衣 | 1 | 男士 > 上衣 |
2 | 3 | 球衣 | 2 | 男士 > 上衣 > 球衣 |
空 |男装 | | 1 | 2 |上衣 | 1 |男装 > 上衣 | | 2 | 3 |球衣 | 2 |男装 > 上衣 > 球衣 | | 3 | 4 |英格兰-1 | 3 |男装 > 上衣 > 球衣 > England-1 | 男装 | 3 | 5 |英格兰-2 | 3 |男装 > 上衣 > 球衣 > England-2 |