根据 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