Using the transitive_closure virtual table extension (closure.c) on your
original question (my sqlite3 has everything built-in already, so no need to
load the extension):
Note though that the AVL tree generated by the closure extension is generated
on the fly upon request and does not have a materialized backing store.
create table folders
(
id integer primary key,
parent_id integer references folders,
name text not null collate nocase,
check (not (parent_id is null and id != 1))
);
create index foldersparentid on folders (parent_id);
create virtual table Closure using transitive_closure;
create view folders_closure
as select folders.id as PARENT_ID,
Closure.id as CHILD_ID,
Closure.depth as DEPTH
from folders, Closure
where Closure.root == folders.id
and Closure.tablename = 'folders'
and Closure.idcolumn = 'id'
and Closure.parentcolumn = 'parent_id';
insert into folders values (1, null, 'Folder1'),
(2, 1, 'Folder2'),
(3, 1, 'Folder3'),
(4, 1, 'Folder4'),
(5, 2, 'Folder5'),
(6, 2, 'Folder6');
.head on
.mode column
.width 30 9 38
-- depth first
with foo (id, parent_id, name, level, path)
as (select folders.*, 0, folders.name
from folders
where parent_id is null
union all
select folders.*, level + 1, foo.path || '\' || folders.name
from foo, folders
where folders.parent_id = foo.id
order by 4
)
select substr(' ', 1, (level - 1) * 4) || name as Folder,
coalesce(parent_id, 0) as PARENT_ID,
path as FullPath
from foo;
-- breadth first
with foo (id, parent_id, name, level, path)
as (select folders.*, 0, folders.name
from folders
where parent_id is null
union all
select folders.*, level + 1, foo.path || '\' || folders.name
from foo, folders
where folders.parent_id = foo.id
order by 4 desc
)
select substr(' ', 1, (level - 1) * 4) || name as Folder,
coalesce(parent_id, 0) as PARENT_ID,
path as FullPath
from foo;
-- folders_closure
.width 9 9 9
select *
from folders_closure;
SQLite version 3.27.0 2019-01-31 02:42:47
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> create table folders
...> (
...> id integer primary key,
...> parent_id integer references folders,
...> name text not null collate nocase,
...> check (not (parent_id is null and id != 1))
...> );
sqlite> create index foldersparentid on folders (parent_id);
sqlite>
sqlite> create virtual table Closure using transitive_closure;
sqlite>
sqlite> create view folders_closure
...> as select folders.id as PARENT_ID,
...> Closure.id as CHILD_ID,
...> Closure.depth as DEPTH
...> from folders, Closure
...> where Closure.root == folders.id
...> and Closure.tablename = 'folders'
...> and Closure.idcolumn = 'id'
...> and Closure.parentcolumn = 'parent_id';
sqlite>
sqlite> insert into folders values (1, null, 'Folder1'),
...> (2, 1, 'Folder2'),
...> (3, 1, 'Folder3'),
...> (4, 1, 'Folder4'),
...> (5, 2, 'Folder5'),
...> (6, 2, 'Folder6');
sqlite> .head on
sqlite> .mode column
sqlite> .width 30 9 38
sqlite>
sqlite> -- depth first
sqlite>
sqlite> with foo (id, parent_id, name, level, path)
...> as (select folders.*, 0, folders.name
...> from folders
...> where parent_id is null
...> union all
...> select folders.*, level + 1, foo.path || '\' || folders.name
...> from foo, folders
...> where folders.parent_id = foo.id
...> order by 4
...> )
...> select substr(' ', 1, (level - 1) * 4) || name as
Folder,
...> coalesce(parent_id, 0) as PARENT_ID,
...> path as FullPath
...> from foo;
Folder PARENT_ID FullPath
------------------------------ ---------
--------------------------------------
Folder1 0 Folder1
Folder2 1 Folder1\Folder2
Folder3 1 Folder1\Folder3
Folder4 1 Folder1\Folder4
Folder5 2 Folder1\Folder2\Folder5
Folder6 2 Folder1\Folder2\Folder6
sqlite>
sqlite>
sqlite> -- breadth first
sqlite>
sqlite> with foo (id, parent_id, name, level, path)
...> as (select folders.*, 0, folders.name
...> from folders
...> where parent_id is null
...> union all
...> select folders.*, level + 1, foo.path || '\' || folders.name
...> from foo, folders
...> where folders.parent_id = foo.id
...> order by 4 desc
...> )
...> select substr(' ', 1, (level - 1) * 4) || name as
Folder,
...> coalesce(parent_id, 0) as PARENT_ID,
...> path as FullPath
...> from foo;
Folder PARENT_ID FullPath
------------------------------ ---------
--------------------------------------
Folder1 0 Folder1
Folder2 1 Folder1\Folder2
Folder5 2 Folder1\Folder2\Folder5
Folder6 2 Folder1\Folder2\Folder6
Folder3 1 Folder1\Folder3
Folder4 1 Folder1\Folder4
sqlite>
sqlite> -- folders_closure
sqlite>
sqlite> .width 9 9 9
sqlite>
sqlite> select *
...> from folders_closure;
PARENT_ID CHILD_ID DEPTH
--------- --------- ---------
1 1 0
1 2 1
1 3 1
1 4 1
1 5 2
1 6 2
2 2 0
2 5 1
2 6 1
3 3 0
4 4 0
5 5 0
6 6 0
sqlite>
---
The fact that there's a Highway to Hell but only a Stairway to Heaven says a
lot about anticipated traffic volume.
_______________________________________________
sqlite-users mailing list
[email protected]
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users