13. すべてのノードとその階層情報の取得
distance: ルートノードからの距離
cf.
WITH RECURSIVE department_tree AS (
SELECT d.*, dal.parent_id, 0 distance
FROM department d
JOIN department_adjacency_list dal USING (department_id)
WHERE dal.parent_id IS NULL
UNION ALL
SELECT d.*, dal.parent_id, dt.distance + 1
FROM department d
JOIN department_adjacency_list dal USING (department_id)
JOIN department_tree dt ON dal.parent_id =
dt.department_id
)
SELECT *
FROM department_tree;
MySQL :: MySQL 8.4 Reference Manual :: 15.2.20
WITH (Common Table Expressions)
13
15. 特定のノードからの子孫ノードの取得
distance: ノード 10 からの距離
WITH RECURSIVE department_tree AS (
SELECT d.*, dal.parent_id, 0 distance
FROM department d
JOIN department_adjacency_list dal USING (department_id)
WHERE d.department_id = 10
UNION ALL
SELECT d.*, dal.parent_id, dt.distance + 1
FROM department d
JOIN department_adjacency_list dal USING (department_id)
JOIN department_tree dt ON dal.parent_id =
dt.department_id
)
SELECT *
FROM department_tree;
15
29. 特定のノードからの子孫ノードの取得
depth: ルートノードからの距離
SELECT d.*, dpe.path,
CHAR_LENGTH(dpe.path) - CHAR_LENGTH(REPLACE(dpe.path, '/',
'')) - 1 depth
FROM department d
JOIN department_path_enumeration dpe USING (department_id)
WHERE dpe.path LIKE CONCAT((
SELECT path
FROM department_path_enumeration
WHERE department_id = 10
), '%');
29
31. 特定のノードの子ノードの取得
SELECT d.*
FROM department d
JOIN department_path_enumeration dpe USING (department_id)
WHERE dpe.path REGEXP CONCAT((
SELECT path
FROM department_path_enumeration
WHERE department_id = 10
), 'd+/$');
31
33. 特定のノードの親ノードの取得
SELECT d.*
FROM department d
JOIN department_path_enumeration dpe USING (department_id)
WHERE dpe.path = (
SELECT CASE WHEN path = CONCAT(department_id, '/') THEN
NULL
ELSE
REGEXP_REPLACE(path, '^(.+/)d+/$', '$1')
END
FROM department_path_enumeration
WHERE department_id = 10
);
33
43. 特定のノードからの子孫ノードの取得
SELECT d.*, dns.left, dns.right, dns.depth
FROM department d
JOIN department_nested_sets dns USING (department_id)
JOIN department_nested_sets dns2 ON dns.left BETWEEN
dns2.left AND dns2.right
WHERE dns2.department_id = 10;
43
45. 特定のノードの子ノードの取得
SELECT d.*
FROM department d
JOIN department_nested_sets dns USING (department_id)
JOIN department_nested_sets dns2 ON dns.left BETWEEN
dns2.left AND dns2.right
WHERE dns2.department_id = 10
AND dns.depth = (
SELECT depth
FROM department_nested_sets
WHERE department_id = 10
) + 1;
45
47. 特定のノードの親ノードの取得
SELECT d.*
FROM department d
JOIN department_nested_sets dns USING (department_id)
JOIN department_nested_sets dns2 ON dns2.left BETWEEN
dns.left AND dns.right
WHERE dns2.department_id = 10
AND dns.depth + 1 = (
SELECT depth
FROM department_nested_sets
WHERE department_id = 10
);
47
59. 特定のノードの子ノードの取得
SELECT d.*
FROM department d
JOIN department_closure_table dct
ON d.department_id = dct.descendant
WHERE dct.ancestor = 10
AND dct.path_length = 1;
59
61. 特定のノードの親ノードの取得
SELECT d.*
FROM department d
JOIN department_closure_table dct
ON d.department_id = dct.ancestor
WHERE dct.descendant = 10
AND dct.path_length = 1;
61
67. 第9章 一歩進んだ論理設計 ~SQLで木構造を扱
う
『達人に学ぶDB設計 徹底指南書』
『プログラマのためのSQLグラフ原論』
What are the options for storing hierarchical data
in a relational database? - Stack Overflow
67