sqlite3上的基本递归查询?

Eri*_*ric 31 sql sqlite hierarchical-data

我有一个简单的sqlite3表,如下所示:

Table: Part
Part    SuperPart
wk0Z    wk00
wk06    wk02
wk07    wk02
eZ01    eZ00
eZ02    eZ00
eZ03    eZ01
eZ04    eZ01
Run Code Online (Sandbox Code Playgroud)

我需要运行一个递归查询来查找给定SuperPart及其所有子组的所有对.所以我要说我有eZ00.eZ00是eZ01的超级部件,eZ01是eZ03的超级部件.结果必须不仅包括对(eZ00,eZ01)和(eZ01和eZ03),还必须包括对(eZ00,eZ03).

我知道还有其他方法来定义表格,但我在这里别无选择.我知道如果我知道树的深度,我可以使用几个工会,但我不会总是知道我想去的深度.它有助于拥有像WITH RECURSIVE这样的东西,甚至只是WITH(,,)AS x,但对于我搜索过的东西,这在sqlite中是不可能的,对吧?

有没有办法在sqlite3中执行此递归查询?

更新:

当提出这个问题时,SQLite不支持递归查询,但正如@lunicon所述,SQLite现在支持递归CTE,因为3.8.3 sqlite.org/lang_with.html

mu *_*ort 32

如果您有幸使用SQLite 3.8.3或更高版本,那么您可以使用WITH访问递归和非递归CTE :

在此输入图像描述

感谢lunicon让我们了解这个SQLite更新.


3.8.3之前的版本中,SQLite不支持递归CTE(或者根本不支持CTE),因此SQLite中没有WITH.由于你不知道它有多深,你不能使用标准的JOIN技巧伪造递归CTE.您必须以艰难的方式执行此操作并在客户端代码中实现递归:

  • 抓取初始行和子部件ID.
  • 获取子部件的行和子部件ID.
  • 重复直到什么都没有回来.

  • 自[3.8.3](http://sqlite.org/releaselog/3_8_3.html)SQLite支持递归CTE!请参阅示例http://sqlite.org/lang_with.html (6认同)

Ale*_*der 8

根据在带有文档的 sqlite中找到的示例,查询

DROP TABLE IF EXISTS parts;
CREATE TABLE parts (part, superpart);
INSERT INTO parts VALUES("wk0Z", "wk00");
INSERT INTO parts VALUES("wk06", "wk02");
INSERT INTO parts VALUES("wk07", "wk02");
INSERT INTO parts VALUES("eZ01", "eZ00");
INSERT INTO parts VALUES("eZ02", "eZ00");
INSERT INTO parts VALUES("eZ03", "eZ01");
INSERT INTO parts VALUES("eZ04", "eZ01");

WITH RECURSIVE
  under_part(parent,part,level) AS (
     VALUES('?', 'eZ00', 0)
     UNION ALL
     SELECT parts.superpart, parts.part, under_part.level+1 
        FROM parts, under_part
     WHERE parts.superpart=under_part.part
  )
  SELECT SUBSTR('..........',1,level*3) || "(" || parent || ", " || part || ")" FROM under_part
  ;
Run Code Online (Sandbox Code Playgroud)

会输出

  (?, eZ00)
  ...(eZ00, eZ01)
  ...(eZ00, eZ02)
  ......(eZ01, eZ03)
  ......(eZ01, eZ04)
Run Code Online (Sandbox Code Playgroud)

正如“应该是”预期的那样

递归表的初始记录可以替换为

VALUES ((SELECT superpart FROM parts WHERE part='eZ00'), 'eZ00', 0)
Run Code Online (Sandbox Code Playgroud)

为了获得初始超部分的父级,尽管在这种情况下根本没有父级。

  • 如果这对初学者来说不是最糟糕的例子 (3认同)
  • 我不明白你的意思......这个例子正是发布的问题给出的例子 (3认同)

Rom*_*ych 7

在此SQLite版本3.8.3中,2014-02-03增加了对CTE的支持.这是文档WITH子句 示例:

WITH RECURSIVE
cnt(x) AS (
 SELECT 1
 UNION ALL
 SELECT x+1 FROM cnt
  LIMIT 1000000
)
SELECT x FROM cnt;
Run Code Online (Sandbox Code Playgroud)

  • 提供的示例代码摘自[docs](http://www.sqlite.org/lang_with.html#rcex1)关于查询优化器的摘录.它没有提供如何查询父子记录层次结构的示例.它只是指出在SQLite中现在支持递归,OP已经找到了. (6认同)
  • 该示例没有添加任何内容作为原始问题的答案. (3认同)
  • @Eric我没有否决你的问题,我正在寻求解决方案,当我发现它时,我决定添加答案。 (2认同)

Pir*_*App 7

这是我能想到的最基本的查询,它生成一个系列,我们从 1,2 开始并不断加 1 直到达到 20。没有多大用处,但稍微玩一下这将有助于您构建更复杂的递归查询

最基本的系列

WITH b(x,y) AS 
(
    SELECT 1,2 
    UNION ALL 
    SELECT x+ 1, y + 1 
    FROM b 
    WHERE x < 20
) SELECT * FROM b;
Run Code Online (Sandbox Code Playgroud)

印刷

1|2
2|3
3|4
4|5
5|6
6|7
7|8
8|9
9|10
10|11
11|12
12|13
13|14
14|15
15|16
16|17
17|18
18|19
19|20
20|21
Run Code Online (Sandbox Code Playgroud)

这是另一个生成斐波那契数的简单示例,我们从 a = 0, b = 1 开始,然后转到 a = b, b = a + b 就像您在任何编程语言中所做的一样

斐波那契数列

WITH b(x,y) AS 
(
    SELECT 0,1 
    UNION ALL 
    SELECT y, x + y 
    FROM b 
    WHERE x < 10000
) select * FROM b;
Run Code Online (Sandbox Code Playgroud)

印刷

0|1
1|1
1|2
2|3
3|5
5|8
8|13
13|21
21|34
34|55
55|89
89|144
144|233
233|377
377|610
610|987
987|1597
1597|2584
2584|4181
4181|6765
6765|10946
10946|17711
Run Code Online (Sandbox Code Playgroud)