使用 H2 DB 和 SQL 递归拆分路径
Recursive split of path with H2 DB and SQL
我有以下常见形式的路径名(路径深度不限):
/a/b/c/d/e/...
例子
/a/b/c/d/e
预期结果
我现在想要实现的是将路径拆分为 table 包含文件夹和各自的父级:
parent
folder
/a/b/c/d/
e
/a/b/c/
d
/a/b/
c
/a/
b
/
a
H2 db 的能力在拆分字符串时有点受限,因此我的假设是它必须递归解决(特别是因为路径深度不受限制)。
任何帮助将不胜感激:)
做这样的事情:
with recursive
p(p) as (select '/a/b/c/d/e' as p),
t(path, parent, folder, i) as (
select
p,
REGEXP_REPLACE(p, '(.*)/\w+', ''),
REGEXP_REPLACE(p, '.*/(\w+)', ''),
1
from p
union
select
t.parent,
REGEXP_REPLACE(t.parent, '(.*)/\w+', ''),
REGEXP_REPLACE(t.parent, '.*/(\w+)', ''),
t.i + 1
from t
where t.parent != ''
)
select *
from t;
导致
|PATH |PARENT |FOLDER|I |
|----------|--------|------|---|
|/a/b/c/d/e|/a/b/c/d|e |1 |
|/a/b/c/d |/a/b/c |d |2 |
|/a/b/c |/a/b |c |3 |
|/a/b |/a |b |4 |
|/a | |a |5 |
不确定您是否真的对尾随 /
个字符感兴趣,但您可以根据需要轻松修复查询。
您需要使用递归查询,例如:
WITH RECURSIVE CTE(S, F, T) AS (
SELECT '/a/b/c/d/e', 0, 1
UNION ALL
SELECT S, T, LOCATE('/', S, T + 1)
FROM CTE
WHERE T <> 0
)
SELECT
SUBSTRING(S FROM 1 FOR F) PARENT,
SUBSTRING(S FROM F + 1 FOR
CASE T WHEN 0 THEN CHARACTER_LENGTH(S) ELSE T - F - 1 END) FOLDER
FROM CTE WHERE F > 0;
它产生
PARENT
FOLDER
/
a
/a/
b
/a/b/
c
/a/b/c/
d
/a/b/c/d/
e
我有以下常见形式的路径名(路径深度不限):
/a/b/c/d/e/...
例子
/a/b/c/d/e
预期结果
我现在想要实现的是将路径拆分为 table 包含文件夹和各自的父级:
parent | folder |
---|---|
/a/b/c/d/ | e |
/a/b/c/ | d |
/a/b/ | c |
/a/ | b |
/ | a |
H2 db 的能力在拆分字符串时有点受限,因此我的假设是它必须递归解决(特别是因为路径深度不受限制)。
任何帮助将不胜感激:)
做这样的事情:
with recursive
p(p) as (select '/a/b/c/d/e' as p),
t(path, parent, folder, i) as (
select
p,
REGEXP_REPLACE(p, '(.*)/\w+', ''),
REGEXP_REPLACE(p, '.*/(\w+)', ''),
1
from p
union
select
t.parent,
REGEXP_REPLACE(t.parent, '(.*)/\w+', ''),
REGEXP_REPLACE(t.parent, '.*/(\w+)', ''),
t.i + 1
from t
where t.parent != ''
)
select *
from t;
导致
|PATH |PARENT |FOLDER|I |
|----------|--------|------|---|
|/a/b/c/d/e|/a/b/c/d|e |1 |
|/a/b/c/d |/a/b/c |d |2 |
|/a/b/c |/a/b |c |3 |
|/a/b |/a |b |4 |
|/a | |a |5 |
不确定您是否真的对尾随 /
个字符感兴趣,但您可以根据需要轻松修复查询。
您需要使用递归查询,例如:
WITH RECURSIVE CTE(S, F, T) AS (
SELECT '/a/b/c/d/e', 0, 1
UNION ALL
SELECT S, T, LOCATE('/', S, T + 1)
FROM CTE
WHERE T <> 0
)
SELECT
SUBSTRING(S FROM 1 FOR F) PARENT,
SUBSTRING(S FROM F + 1 FOR
CASE T WHEN 0 THEN CHARACTER_LENGTH(S) ELSE T - F - 1 END) FOLDER
FROM CTE WHERE F > 0;
它产生
PARENT | FOLDER |
---|---|
/ | a |
/a/ | b |
/a/b/ | c |
/a/b/c/ | d |
/a/b/c/d/ | e |