简体   繁体   English

在树结构表中查找空节点的 SQL 查询

[英]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 ID name姓名 type类型 depth深度 parentId父母身份
1 1 1 1 node节点 0 0
2 2 2 2 node节点 1 1 1 1
3 3 3 3 node节点 1 1 1 1
4 4 4 4 node节点 2 2 2 2
5 5 5 5 node节点 2 2 3 3
6 6 6 6 node节点 2 2 3 3
7 7 7 7 node节点 3 3 4 4
8 8 8 8 node节点 3 3 6 6
9 9 ** ** data数据 2 2 2 2
10 10 ** ** data数据 2 2 2 2
11 11 ** ** data数据 3 3 4 4
12 12 ** ** data数据 3 3 5 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM