邻接表模型重复 parent & children
Adjacency list model duplicate parent & children
MySQL 中的分层数据使用邻接表模型
我把这个 table 命名为 node_structur_data
CREATE TABLE node_structure_data (
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
title VARCHAR(455) NOT NULL,
parent_id INT(10) UNSIGNED DEFAULT NULL,
PRIMARY KEY (id),
FOREIGN KEY (parent_id) REFERENCES node_structure_data (id)
ON DELETE CASCADE ON UPDATE CASCADE
);
输出:
id title parent_id
1 Division NULL
2 Site 1 1
3 Paper 2
4 ms1 3
如何复制节点及其 children?
例如Site 1
ID & parent_id 应该是唯一的,但标题应该保持不变。
预期输出:
id title parent_id
1 Division NULL
2 Site 1 1
3 Paper 2
4 ms1 3
5 Site 1 1
6 Paper 5
7 ms1 6
以下方法首先估计新的最大值,然后使用递归 cte 查找所需节点的所有子节点 'Site 1' 并确定它们的新可能 parent_id
如果没有其他并发写入table.
我会推荐运行以下在transaction and lockingtable操作过程中防止并发table修改。
为了测试这种方法,我添加了一些额外的示例数据,这些数据包含在下面,但是您可能会在带有初始示例数据的演示中看到该方法 here
请参阅下面工作数据库 fiddle 的输出:
架构(MySQL v8.0)
CREATE TABLE node_structure_data (
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
title VARCHAR(455) NOT NULL,
parent_id INT(10) UNSIGNED DEFAULT NULL,
PRIMARY KEY (id),
FOREIGN KEY (parent_id) REFERENCES node_structure_data (id)
ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO node_structure_data
(`id`, `title`, `parent_id`)
VALUES
('1', 'Division', NULL),
('2', 'Site 1', '1'),
('3', 'Paper', '2'),
('4', 'ms1', '3'),
('5', 'ms2', '3'),
('6', 'os1', '4'),
('7', 'os2', '4'),
('8', 'gs1', '1'),
('9', 'hs1', '3'),
('10','js1','9');
查询#1
select 'Before Insert';
Before Insert
Before Insert
查询 #2
select * from node_structure_data;
id
title
parent_id
1
Division
2
Site 1
1
3
Paper
2
4
ms1
3
5
ms2
3
6
os1
4
7
os2
4
8
gs1
1
9
hs1
3
10
js1
9
查询#3
select 'Possible Data Changes';
Possible Data Changes
Possible Data Changes
查询#4
with recursive max_id AS (
SELECT MAX(id) as id FROM node_structure_data
),
child_nodes AS (
SELECT
n.id,
title,
parent_id,
m.id+1 as new_id,
parent_id as new_parent_id
FROM
node_structure_data n
CROSS JOIN
max_id as m
WHERE
title='Site 1'
UNION ALL
SELECT
n.id,
n.title,
n.parent_id,
@row_num:=IF(@row_num=0,c.new_id,0) + 1 + @row_num as new_id,
c.new_id
FROM
child_nodes c
INNER JOIN
node_structure_data n ON n.parent_id = c.id
CROSS JOIN (
SELECT @row_num:=0 as rn
) as vars
)
SELECT * FROM child_nodes;
id
title
parent_id
new_id
new_parent_id
2
Site 1
1
11
1
3
Paper
2
12
11
4
ms1
3
13
12
5
ms2
3
14
12
9
hs1
3
15
12
6
os1
4
16
13
7
os2
4
17
13
10
js1
9
18
15
查询 #5 - 执行实际插入
INSERT INTO node_structure_data (title,parent_id)
with recursive max_id AS (
SELECT MAX(id) as id FROM node_structure_data
),
child_nodes AS (
SELECT
n.id,
title,
parent_id,
m.id+1 as new_id,
parent_id as new_parent_id
FROM
node_structure_data n
CROSS JOIN
max_id as m
WHERE
title='Site 1'
UNION ALL
SELECT
n.id,
n.title,
n.parent_id,
@row_num:=IF(@row_num=0,c.new_id,0) + 1 + @row_num as new_id,
c.new_id
FROM
child_nodes c
INNER JOIN
node_structure_data n ON n.parent_id = c.id
CROSS JOIN (
SELECT @row_num:=0 as rn
) as vars
)
SELECT title,new_parent_id FROM child_nodes ORDER BY new_id;
没有要显示的结果。
查询 #6
select 'AFTER INSERT';
AFTER INSERT
AFTER INSERT
查询 #7
select * from node_structure_data;
id
title
parent_id
1
Division
2
Site 1
1
3
Paper
2
4
ms1
3
5
ms2
3
6
os1
4
7
os2
4
8
gs1
1
9
hs1
3
10
js1
9
11
Site 1
1
12
Paper
11
13
ms1
12
14
ms2
12
15
hs1
12
16
os1
13
17
os2
13
18
js1
15
让我知道这是否适合你。
MySQL 中的分层数据使用邻接表模型
我把这个 table 命名为 node_structur_data
CREATE TABLE node_structure_data (
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
title VARCHAR(455) NOT NULL,
parent_id INT(10) UNSIGNED DEFAULT NULL,
PRIMARY KEY (id),
FOREIGN KEY (parent_id) REFERENCES node_structure_data (id)
ON DELETE CASCADE ON UPDATE CASCADE
);
输出:
id title parent_id
1 Division NULL
2 Site 1 1
3 Paper 2
4 ms1 3
如何复制节点及其 children?
例如Site 1
ID & parent_id 应该是唯一的,但标题应该保持不变。
预期输出:
id title parent_id
1 Division NULL
2 Site 1 1
3 Paper 2
4 ms1 3
5 Site 1 1
6 Paper 5
7 ms1 6
以下方法首先估计新的最大值,然后使用递归 cte 查找所需节点的所有子节点 'Site 1' 并确定它们的新可能 parent_id
如果没有其他并发写入table.
我会推荐运行以下在transaction and lockingtable操作过程中防止并发table修改。
为了测试这种方法,我添加了一些额外的示例数据,这些数据包含在下面,但是您可能会在带有初始示例数据的演示中看到该方法 here
请参阅下面工作数据库 fiddle 的输出:
架构(MySQL v8.0)
CREATE TABLE node_structure_data (
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
title VARCHAR(455) NOT NULL,
parent_id INT(10) UNSIGNED DEFAULT NULL,
PRIMARY KEY (id),
FOREIGN KEY (parent_id) REFERENCES node_structure_data (id)
ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO node_structure_data
(`id`, `title`, `parent_id`)
VALUES
('1', 'Division', NULL),
('2', 'Site 1', '1'),
('3', 'Paper', '2'),
('4', 'ms1', '3'),
('5', 'ms2', '3'),
('6', 'os1', '4'),
('7', 'os2', '4'),
('8', 'gs1', '1'),
('9', 'hs1', '3'),
('10','js1','9');
查询#1
select 'Before Insert';
Before Insert |
---|
Before Insert |
查询 #2
select * from node_structure_data;
id | title | parent_id |
---|---|---|
1 | Division | |
2 | Site 1 | 1 |
3 | Paper | 2 |
4 | ms1 | 3 |
5 | ms2 | 3 |
6 | os1 | 4 |
7 | os2 | 4 |
8 | gs1 | 1 |
9 | hs1 | 3 |
10 | js1 | 9 |
查询#3
select 'Possible Data Changes';
Possible Data Changes |
---|
Possible Data Changes |
查询#4
with recursive max_id AS (
SELECT MAX(id) as id FROM node_structure_data
),
child_nodes AS (
SELECT
n.id,
title,
parent_id,
m.id+1 as new_id,
parent_id as new_parent_id
FROM
node_structure_data n
CROSS JOIN
max_id as m
WHERE
title='Site 1'
UNION ALL
SELECT
n.id,
n.title,
n.parent_id,
@row_num:=IF(@row_num=0,c.new_id,0) + 1 + @row_num as new_id,
c.new_id
FROM
child_nodes c
INNER JOIN
node_structure_data n ON n.parent_id = c.id
CROSS JOIN (
SELECT @row_num:=0 as rn
) as vars
)
SELECT * FROM child_nodes;
id | title | parent_id | new_id | new_parent_id |
---|---|---|---|---|
2 | Site 1 | 1 | 11 | 1 |
3 | Paper | 2 | 12 | 11 |
4 | ms1 | 3 | 13 | 12 |
5 | ms2 | 3 | 14 | 12 |
9 | hs1 | 3 | 15 | 12 |
6 | os1 | 4 | 16 | 13 |
7 | os2 | 4 | 17 | 13 |
10 | js1 | 9 | 18 | 15 |
查询 #5 - 执行实际插入
INSERT INTO node_structure_data (title,parent_id)
with recursive max_id AS (
SELECT MAX(id) as id FROM node_structure_data
),
child_nodes AS (
SELECT
n.id,
title,
parent_id,
m.id+1 as new_id,
parent_id as new_parent_id
FROM
node_structure_data n
CROSS JOIN
max_id as m
WHERE
title='Site 1'
UNION ALL
SELECT
n.id,
n.title,
n.parent_id,
@row_num:=IF(@row_num=0,c.new_id,0) + 1 + @row_num as new_id,
c.new_id
FROM
child_nodes c
INNER JOIN
node_structure_data n ON n.parent_id = c.id
CROSS JOIN (
SELECT @row_num:=0 as rn
) as vars
)
SELECT title,new_parent_id FROM child_nodes ORDER BY new_id;
没有要显示的结果。
查询 #6
select 'AFTER INSERT';
AFTER INSERT |
---|
AFTER INSERT |
查询 #7
select * from node_structure_data;
id | title | parent_id |
---|---|---|
1 | Division | |
2 | Site 1 | 1 |
3 | Paper | 2 |
4 | ms1 | 3 |
5 | ms2 | 3 |
6 | os1 | 4 |
7 | os2 | 4 |
8 | gs1 | 1 |
9 | hs1 | 3 |
10 | js1 | 9 |
11 | Site 1 | 1 |
12 | Paper | 11 |
13 | ms1 | 12 |
14 | ms2 | 12 |
15 | hs1 | 12 |
16 | os1 | 13 |
17 | os2 | 13 |
18 | js1 | 15 |
让我知道这是否适合你。