teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

2

修正

2021/05/26 05:45

投稿

yambejp
yambejp

スコア117906

answer CHANGED
@@ -10,7 +10,7 @@
10
10
  (3,'タイトルC',null),
11
11
  (4,'タイトルA-1',1),
12
12
  (5,'タイトルA-1-1',4),
13
- (6,'タイトルA-1-2',5),
13
+ (6,'タイトルA-1-2',4),
14
14
  (7,'タイトルA-2',1);
15
15
  ```
16
16
  # procedure

1

参考

2021/05/26 05:45

投稿

yambejp
yambejp

スコア117906

answer CHANGED
@@ -1,2 +1,60 @@
1
1
  いまのデータ管理方法では何をやっても無駄でしょう
2
- ちゃんとやるなら入れ子集合モデルという方式をつかいます。
2
+ ちゃんとやるなら入れ子集合モデルという方式をつかいます。
3
+
4
+ # sample
5
+ ```SQL
6
+ create table tbl (id int primary key,name varchar(30),parent_id int,level int,l int,r int);
7
+ insert into tbl(id,name,parent_id) values
8
+ (1,'タイトルA',null),
9
+ (2,'タイトルB',null),
10
+ (3,'タイトルC',null),
11
+ (4,'タイトルA-1',1),
12
+ (5,'タイトルA-1-1',4),
13
+ (6,'タイトルA-1-2',5),
14
+ (7,'タイトルA-2',1);
15
+ ```
16
+ # procedure
17
+ ```SQL
18
+ DROP PROCEDURE IF EXISTS SET_LR;
19
+ DELIMITER //
20
+ CREATE PROCEDURE SET_LR()
21
+ BEGIN
22
+ DECLARE a INT DEFAULT 0;
23
+ DECLARE done INT DEFAULT 0;
24
+ DECLARE CUR CURSOR FOR
25
+ SELECT id FROM tbl WHERE level=0 ORDER BY parent_id ASC,id DESC;
26
+ DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
27
+ UPDATE tbl SET level=0,l=0,r=0;
28
+
29
+ UPDATE tbl SET level=1,l=(SELECT @a:=@a+1 FROM (SELECT @a:=0) AS sub),r=@a:=@a+1
30
+ WHERE parent_id IS NULL
31
+ ORDER BY id;
32
+
33
+ OPEN CUR;
34
+ REPEAT
35
+ FETCH CUR INTO a;
36
+ IF NOT done THEN
37
+ SET @id=a;
38
+ 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=?';
39
+
40
+ PREPARE stmt from @sql;
41
+ EXECUTE stmt USING @id;
42
+ 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=?';
43
+
44
+ PREPARE stmt from @sql;
45
+ EXECUTE stmt USING @id;
46
+ END IF;
47
+ UNTIL done END REPEAT;
48
+ CLOSE CUR;
49
+ END
50
+ //
51
+ DELIMITER ;
52
+ ```
53
+ # 実行
54
+ ```SQL
55
+ call set_lr;
56
+ ```
57
+ # 表示
58
+ ```SQL
59
+ select * from tbl order by l;
60
+ ```