[英]SQL query to find empty nodes in a tree structure table
I'm developing an Android application that stores some of its data as a tree like structure in an SQLite table.我正在开发一个 Android 应用程序,它将它的一些数据存储为 SQLite 表中的树状结构。
As an example, the relevant part of the table has the following structure:例如,表的相关部分具有以下结构:
id ![]() |
name![]() |
type![]() |
depth![]() |
parentId![]() |
---|---|---|---|---|
1 ![]() |
1 ![]() |
node![]() |
0 ![]() |
|
2 ![]() |
2 ![]() |
node![]() |
1 ![]() |
1 ![]() |
3 ![]() |
3 ![]() |
node![]() |
1 ![]() |
1 ![]() |
4 ![]() |
4 ![]() |
node![]() |
2 ![]() |
2 ![]() |
5 ![]() |
5 ![]() |
node![]() |
2 ![]() |
3 ![]() |
6 ![]() |
6 ![]() |
node![]() |
2 ![]() |
3 ![]() |
7 ![]() |
7 ![]() |
node![]() |
3 ![]() |
4 ![]() |
8 ![]() |
8 ![]() |
node![]() |
3 ![]() |
6 ![]() |
9 ![]() |
** ![]() |
data![]() |
2 ![]() |
2 ![]() |
10 ![]() |
** ![]() |
data![]() |
2 ![]() |
2 ![]() |
11 ![]() |
** ![]() |
data![]() |
3 ![]() |
4 ![]() |
12 ![]() |
** ![]() |
data![]() |
3 ![]() |
5 ![]() |
The following image represents the same data of the table:下图代表表中相同的数据:
The question is: How can I get all the nodes ( type = node
) that have no data
structures below them?问题是:我怎样才能得到下面没有
data
结构的所有节点( type = node
)? In the example the result would be nodes 6, 7 and 8 which are colored green in the tree.在示例中,结果将是节点 6、7 和 8,它们在树中被涂成绿色。
For now, I'm only able to get empty nodes on the deepest part of the tree with the following query:目前,我只能使用以下查询在树的最深处获取空节点:
SELECT id
FROM treeTable
WHERE type = 'node'
AND id NOT IN
(SELECT DISTINCT parentId
FROM treeTable
WHERE parentId IS NOT NULL)
My problem is with that node number 6. It should be returned in the query but, as it appears as a parent of another node I don't know how to filter it out.我的问题是那个节点号 6。它应该在查询中返回,但是因为它显示为另一个节点的父节点,所以我不知道如何将其过滤掉。 Any ideas are welcome.
欢迎任何想法。
After some research based on the @tinazmu's answer , I finally came up with a query that seems to be working fine for my case in SQLite.在基于@tinazmu 的回答进行了一些研究之后,我终于想出了一个查询,该查询似乎适用于我在 SQLite 中的情况。
WITH AncestryTree AS (
SELECT id, parentId, type
FROM Tree
WHERE parentId IS NOT NULL
UNION ALL
SELECT T.id, AT.parentId, T.type
FROM AncestryTree AT
JOIN Tree T ON AT.id = T.parentId
)
SELECT id
FROM Tree
WHERE type = 'node'
AND id NOT IN (
SELECT DISTINCT parentId
FROM AncestryTree
WHERE type = 'data'
)
The query can be tested in db-fiddle , but it'd be great if someone pointed out any flaws or optimizations to this query.该查询可以在db-fiddle中进行测试,但如果有人指出此查询的任何缺陷或优化,那就太好了。
I could use recursion to find the data nodes within each 'node' node.我可以使用递归来查找每个“节点”节点中的数据节点。
with treeTable as (
select *
from (values
(1,'1','node',0,null)
,(2,'2','node',1,1)
,(3,'3','node',1,1)
,(4,'4','node',2,2)
,(5,'5','node',2,3)
,(6,'6','node',2,3)
,(7,'7','node',3,4)
,(8,'8','node',3,6)
,(9,'**','data',2,2)
,(10,'**','data',2,2)
,(11,'**','data',3,4)
,(12,'**','data',3,5)
) T(id, name, type, depth, parentId)
),
Hry as (
SELECT StartNode=TN.id, ThisNode=TN.id, TN.name, tn.type, tn.depth, L=0
FROM treeTable TN
union all
SELECT StartNode=H.StartNode, ThisNode=TN.id, TN.name, TN.type, TN.depth, L=L+1
FROM treeTable TN
inner join
Hry H
on H.ThisNode=TN.ParentId
)
/* Now repeat for each 'node' node: recursively traverse each sub-tree and see if there are data nodes underneath */
select T.id
from treeTable T
left join
Hry H
on T.id=H.StartNode
and H.type='data'
where T.type='node'
and H.StartNode is null
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.