根据 SQLite 中的 list_order 使用路径索引订购嵌套 table
Order a nested table with path index according to list_order in SQLite
我有一个 SQL table 具有此嵌套结构:
CREATE TABLE items (`id` INTEGER, `item_name` VARCHAR(6), `parent_id` INTEGER, `list_order` INTEGER);
我的 SQLite 版本不支持 window 功能,目前我在 link SQLite query 的查询返回结果如下,但没有按照list_order,另一个细节是 list_order 列的所有值都可以为零。
id name_item parent_id level path_index list_order
---------------------------------------------------------------
1 Pois 0 0 1 4
2 Então 0 0 2 5
3 Teste 0 0 3 3
11 Teste 3 3 1 3.1 2
12 Teste 2 3 1 3.2 0
13 Teste 1 3 1 3.3 1
4 Fundo 0 0 4 2
7 Profundo 4 1 4.1 1
8 Dhdhd 4 1 4.2 0
9 Gagagaga 8 2 4.2.1 1
10 Fsfsfsfs 8 2 4.2.2 0
5 Profundo 0 0 5 1
6 Gigante 0 0 6 6
14 Teste 0 0 7 0
我希望 path_index 列跟随 list_order 和级别列,如下所示:
id name_item parent_id level path_index list_order
---------------------------------------------------------------
14 Teste 0 0 1 0
5 Profundo 0 0 2 1
4 Fundo 0 0 3 2
8 Dhdhd 4 1 3.1 0
10 Fsfsfsfs 8 2 3.1.1 0
9 Gagagaga 8 2 3.1.2 1
7 Profundo 4 1 3.2 1
3 Teste 0 0 4 3
12 Teste 2 3 1 4.1 0
13 Teste 1 3 1 4.2 1
11 Teste 3 3 1 4.3 2
1 Pois 0 0 5 4
2 Então 0 0 6 5
6 Gigante 0 0 7 6
如何对齐根据 list_order 和级别排序的 path_index 列?
使用递归 CTE 中的列 list_order
创建每个项目的 path_index
并按其排序:
WITH cte AS (
SELECT *, 0 level,
(list_order + 1) || '' path_index,
printf('%06d', list_order + 1) path_exp
FROM items
WHERE parent_id = 0
UNION ALL
SELECT i.*, c.level + 1,
c.path_index || '.' || (i.list_order + 1),
path_exp || printf('%06d', i.list_order + 1)
FROM items i INNER JOIN cte c
ON c.id = i.parent_id
)
SELECT id, item_name, parent_id, level, path_index, list_order
FROM cte
ORDER BY path_exp
对于 list_order
没有为所有项目定义的情况:
WITH
list_orders AS (
SELECT i1.id, i1.item_name, i1.parent_id,
(SELECT COUNT(i2.id)
FROM items i2
WHERE i2.parent_id = i1.parent_id
AND (i2.list_order < i1.list_order
OR (i2.list_order = i1.list_order AND i2.id < i1.id))
) list_order
FROM items i1
),
cte AS (
SELECT *, 0 level,
(list_order + 1) || '' path_index,
printf('%06d', list_order + 1) path_exp
FROM list_orders
WHERE parent_id = 0
UNION ALL
SELECT li.*, c.level + 1,
c.path_index || '.' || (li.list_order + 1),
path_exp || printf('%06d', li.list_order + 1)
FROM list_orders li INNER JOIN cte c
ON c.id = li.parent_id
)
SELECT id, item_name, parent_id, level, path_index, list_order
FROM cte
ORDER BY path_exp
参见demo。
结果:
id
item_name
parent_id
level
path_index
list_order
14
Teste
0
0
1
0
5
Profundo
0
0
2
1
4
Fundo
0
0
3
2
8
Dhdhd
4
1
3.1
0
10
Fsfsfsfs
8
2
3.1.1
0
9
Gagagaga
8
2
3.1.2
1
7
Profundo
4
1
3.2
1
3
Teste
0
0
4
3
12
Teste 2
3
1
4.1
0
13
Teste 1
3
1
4.2
1
11
Teste 3
3
1
4.3
2
1
Pois
0
0
5
4
2
Então
0
0
6
5
6
Gigante
0
0
7
6
我有一个 SQL table 具有此嵌套结构:
CREATE TABLE items (`id` INTEGER, `item_name` VARCHAR(6), `parent_id` INTEGER, `list_order` INTEGER);
我的 SQLite 版本不支持 window 功能,目前我在 link SQLite query 的查询返回结果如下,但没有按照list_order,另一个细节是 list_order 列的所有值都可以为零。
id name_item parent_id level path_index list_order
---------------------------------------------------------------
1 Pois 0 0 1 4
2 Então 0 0 2 5
3 Teste 0 0 3 3
11 Teste 3 3 1 3.1 2
12 Teste 2 3 1 3.2 0
13 Teste 1 3 1 3.3 1
4 Fundo 0 0 4 2
7 Profundo 4 1 4.1 1
8 Dhdhd 4 1 4.2 0
9 Gagagaga 8 2 4.2.1 1
10 Fsfsfsfs 8 2 4.2.2 0
5 Profundo 0 0 5 1
6 Gigante 0 0 6 6
14 Teste 0 0 7 0
我希望 path_index 列跟随 list_order 和级别列,如下所示:
id name_item parent_id level path_index list_order
---------------------------------------------------------------
14 Teste 0 0 1 0
5 Profundo 0 0 2 1
4 Fundo 0 0 3 2
8 Dhdhd 4 1 3.1 0
10 Fsfsfsfs 8 2 3.1.1 0
9 Gagagaga 8 2 3.1.2 1
7 Profundo 4 1 3.2 1
3 Teste 0 0 4 3
12 Teste 2 3 1 4.1 0
13 Teste 1 3 1 4.2 1
11 Teste 3 3 1 4.3 2
1 Pois 0 0 5 4
2 Então 0 0 6 5
6 Gigante 0 0 7 6
如何对齐根据 list_order 和级别排序的 path_index 列?
使用递归 CTE 中的列 list_order
创建每个项目的 path_index
并按其排序:
WITH cte AS (
SELECT *, 0 level,
(list_order + 1) || '' path_index,
printf('%06d', list_order + 1) path_exp
FROM items
WHERE parent_id = 0
UNION ALL
SELECT i.*, c.level + 1,
c.path_index || '.' || (i.list_order + 1),
path_exp || printf('%06d', i.list_order + 1)
FROM items i INNER JOIN cte c
ON c.id = i.parent_id
)
SELECT id, item_name, parent_id, level, path_index, list_order
FROM cte
ORDER BY path_exp
对于 list_order
没有为所有项目定义的情况:
WITH
list_orders AS (
SELECT i1.id, i1.item_name, i1.parent_id,
(SELECT COUNT(i2.id)
FROM items i2
WHERE i2.parent_id = i1.parent_id
AND (i2.list_order < i1.list_order
OR (i2.list_order = i1.list_order AND i2.id < i1.id))
) list_order
FROM items i1
),
cte AS (
SELECT *, 0 level,
(list_order + 1) || '' path_index,
printf('%06d', list_order + 1) path_exp
FROM list_orders
WHERE parent_id = 0
UNION ALL
SELECT li.*, c.level + 1,
c.path_index || '.' || (li.list_order + 1),
path_exp || printf('%06d', li.list_order + 1)
FROM list_orders li INNER JOIN cte c
ON c.id = li.parent_id
)
SELECT id, item_name, parent_id, level, path_index, list_order
FROM cte
ORDER BY path_exp
参见demo。
结果:
id | item_name | parent_id | level | path_index | list_order |
---|---|---|---|---|---|
14 | Teste | 0 | 0 | 1 | 0 |
5 | Profundo | 0 | 0 | 2 | 1 |
4 | Fundo | 0 | 0 | 3 | 2 |
8 | Dhdhd | 4 | 1 | 3.1 | 0 |
10 | Fsfsfsfs | 8 | 2 | 3.1.1 | 0 |
9 | Gagagaga | 8 | 2 | 3.1.2 | 1 |
7 | Profundo | 4 | 1 | 3.2 | 1 |
3 | Teste | 0 | 0 | 4 | 3 |
12 | Teste 2 | 3 | 1 | 4.1 | 0 |
13 | Teste 1 | 3 | 1 | 4.2 | 1 |
11 | Teste 3 | 3 | 1 | 4.3 | 2 |
1 | Pois | 0 | 0 | 5 | 4 |
2 | Então | 0 | 0 | 6 | 5 |
6 | Gigante | 0 | 0 | 7 | 6 |