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
如果您的 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'
我在 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
如果您的 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'