回答編集履歴

2

修正

2021/05/26 05:45

投稿

yambejp
yambejp

スコア116835

test CHANGED
@@ -22,7 +22,7 @@
22
22
 
23
23
  (5,'タイトルA-1-1',4),
24
24
 
25
- (6,'タイトルA-1-2',5),
25
+ (6,'タイトルA-1-2',4),
26
26
 
27
27
  (7,'タイトルA-2',1);
28
28
 

1

参考

2021/05/26 05:45

投稿

yambejp
yambejp

スコア116835

test CHANGED
@@ -1,3 +1,119 @@
1
1
  いまのデータ管理方法では何をやっても無駄でしょう
2
2
 
3
3
  ちゃんとやるなら入れ子集合モデルという方式をつかいます。
4
+
5
+
6
+
7
+ # sample
8
+
9
+ ```SQL
10
+
11
+ create table tbl (id int primary key,name varchar(30),parent_id int,level int,l int,r int);
12
+
13
+ insert into tbl(id,name,parent_id) values
14
+
15
+ (1,'タイトルA',null),
16
+
17
+ (2,'タイトルB',null),
18
+
19
+ (3,'タイトルC',null),
20
+
21
+ (4,'タイトルA-1',1),
22
+
23
+ (5,'タイトルA-1-1',4),
24
+
25
+ (6,'タイトルA-1-2',5),
26
+
27
+ (7,'タイトルA-2',1);
28
+
29
+ ```
30
+
31
+ # procedure
32
+
33
+ ```SQL
34
+
35
+ DROP PROCEDURE IF EXISTS SET_LR;
36
+
37
+ DELIMITER //
38
+
39
+ CREATE PROCEDURE SET_LR()
40
+
41
+ BEGIN
42
+
43
+ DECLARE a INT DEFAULT 0;
44
+
45
+ DECLARE done INT DEFAULT 0;
46
+
47
+ DECLARE CUR CURSOR FOR
48
+
49
+ SELECT id FROM tbl WHERE level=0 ORDER BY parent_id ASC,id DESC;
50
+
51
+ DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
52
+
53
+ UPDATE tbl SET level=0,l=0,r=0;
54
+
55
+
56
+
57
+ UPDATE tbl SET level=1,l=(SELECT @a:=@a+1 FROM (SELECT @a:=0) AS sub),r=@a:=@a+1
58
+
59
+ WHERE parent_id IS NULL
60
+
61
+ ORDER BY id;
62
+
63
+
64
+
65
+ OPEN CUR;
66
+
67
+ REPEAT
68
+
69
+ FETCH CUR INTO a;
70
+
71
+ IF NOT done THEN
72
+
73
+ SET @id=a;
74
+
75
+ SET @sql='UPDATE tbl as a1,tbl as a2,tbl as a3 SET a1.l=a2.l+1,a1.r=a2.l+2,a1.level=a2.level+1,a2.r=a2.r+2,a3.r=a3.r+2 WHERE a1.parent_id=a2.id AND a2.l<a3.r AND a1.id=?';
76
+
77
+
78
+
79
+ PREPARE stmt from @sql;
80
+
81
+ EXECUTE stmt USING @id;
82
+
83
+ SET @sql='UPDATE tbl as a1,tbl as a2,tbl as a3 SET a3.l=a3.l+2 WHERE a1.parent_id=a2.id AND a2.l<a3.l and a3.id!=a1.id AND a1.id=?';
84
+
85
+
86
+
87
+ PREPARE stmt from @sql;
88
+
89
+ EXECUTE stmt USING @id;
90
+
91
+ END IF;
92
+
93
+ UNTIL done END REPEAT;
94
+
95
+ CLOSE CUR;
96
+
97
+ END
98
+
99
+ //
100
+
101
+ DELIMITER ;
102
+
103
+ ```
104
+
105
+ # 実行
106
+
107
+ ```SQL
108
+
109
+ call set_lr;
110
+
111
+ ```
112
+
113
+ # 表示
114
+
115
+ ```SQL
116
+
117
+ select * from tbl order by l;
118
+
119
+ ```