SQLite 递归查询 return 给定路径的 ID

SQLite recursive query to return the ID of a given Path

我在 Sqlite 数据库中存储文件夹层次结构,如下所示:

+----------+---------+----------+
| ParentID | ChildID |   Name   |
+----------+---------+----------+
|        1 |       2 | Folder A |
|        2 |       3 | Folder B |
|        3 |       4 | Folder C |
+----------+---------+----------+

其中 Folder A 是根,结构是:Folder A/Folder B/Folder C.

目前,我有一个递归 CTE,它可以根据文件夹的 ID 导出 文件夹的路径。 (通过在ChildID列中找到ID,然后向上走)

但是,我目前没有一种方法可以根据文件夹的路径导出文件夹的 ID。这肯定有点棘手,因为如果我想查询 table.

,我必须在 / 上拆分字符串

到目前为止,我已经开始递归 CTE:

SELECT Path, ChildID FROM DirectoryStructure, (
    SELECT SUBSTR('Folder A/Folder B/Folder C', 0, Position) as Root, 
           SUBSTR('Folder A/Folder B/Folder C', Position+1) as Path 
    FROM (SELECT INSTR('Folder A/Folder B/Folder C', '/') as Position)
) WHERE Name = Root

这将 return:

+-------------------+---------+
|       Path        | ChildID |
+-------------------+---------+
| Folder B/Folder C |       2 |
+-------------------+---------+

这太完美了,因为我有 Folder A 的 ChildID,还有要处理的下一块路径。现在应该只是递归地执行下一步,我摘下 Folder B(就像我做的 Folder A)并在 DirectoryStructure 中找到条目,其中 ParentID = 2 AND Name = 'Folder B' 得到它的 ChildID 等等。

但是,这就是我遇到麻烦的地方。我想我需要这样的东西:

WITH RECURSIVE GetId(Path, LastChild) AS (
    SELECT Path, ChildID FROM DirectoryStructure, (
        SELECT SUBSTR('Folder A/Folder B/Folder C', 0, Position) as Root, 
               SUBSTR('Folder A/Folder B/Folder C', Position+1) as Path 
        FROM (SELECT INSTR('Folder A/Folder B/Folder C', '/') as Position)
    ) WHERE Name = Root
    UNION ALL
    SELECT Path, ChildID FROM DirectoryStructure, (
        SELECT SUBSTR(GetId.Path, 0, Position) as Root, 
               SUBSTR(GetId.Path, Position+1) as Path
        FROM GetId, (SELECT INSTR(GetId.Path, '/') as Position FROM GetId)
    ) WHERE (ParentID = GetId.LastChild, Name = Root)
) SELECT * from GetId;

玩这个我通常会得到错误:Result: recursive reference in a subquery: GetId

我知道它不希望我在子查询中使用 GetId,但我似乎想不出任何其他方法来完成此操作。

如有任何帮助,我们将不胜感激!

另一种方法是找到每个 child 的路径,然后与搜索路径进行比较:

WITH RECURSIVE CTE AS (
  SELECT ChildId, Name AS Path
  FROM DirectoryStructure
  WHERE ParentID = 1
  UNION ALL
  SELECT d.ChildId, Path || '/' || Name
  FROM DirectoryStructure d
  JOIN CTE ON d.ParentId = CTE.ChildId
)
SELECT *
FROM CTE
WHERE Path = 'Folder A/Folder B/Folder C'

输出:

ChildId     Path
4           Folder A/Folder B/Folder C

Demo on dbfiddle

如果您的 table 很大并且上面的查询太慢,您可以在进行时修剪条目以确保它们与所需的路径匹配到该级别:

WITH RECURSIVE CTE AS (
  SELECT ChildId, Name AS Path
  FROM DirectoryStructure
  WHERE ParentID = 1
    AND 'Folder A/Folder B/Folder C' LIKE Name || '%'
  UNION ALL
  SELECT d.ChildId, Path || '/' || Name
  FROM DirectoryStructure d
  JOIN CTE ON d.ParentId = CTE.ChildId
  WHERE 'Folder A/Folder B/Folder C' LIKE Path || '/' || Name || '%'
)
SELECT *
FROM CTE
WHERE Path = 'Folder A/Folder B/Folder C'

Demo on dbfiddle