如何在Sqlite中设置表来执行递归查询?

时间:2014-02-07 07:29:18

标签: sql sqlite

如果这是一个基本问题,我道歉,但我是数据库新手。我正在使用sqlite来管理某些工具的命令行选项列表。一个简单的版本是:

sqlite> CREATE TABLE option_set (set_id INTEGER, idx INTEGER, value TEXT );
sqlite> INSERT INTO option_set VALUES( 1, 1, 'a' );
sqlite> INSERT INTO option_set VALUES( 1, 2, 'b' );
sqlite> INSERT INTO option_set VALUES( 1, 3, 'c' );
sqlite> SELECT value FROM option_set WHERE set_id=1 ORDER BY idx;
a
b
c

一切正常。我想添加一个增强功能,但是我允许一个option_set包含另一个。例如,如果我将option_set = 2指定为{'d','e',[option_set = 1],'f'},我希望这意味着选项{'d','e','a' ,'b','c','f'}。问题是如何在数据库中表达这一点。我在考虑以下几点:

sqlite> CREATE TABLE option_set (set_id INTEGER, idx INTEGER, contained_set_id INTEGER, value TEXT );
sqlite> INSERT INTO option_set VALUES( 1, 1, NULL, 'a' );
sqlite> INSERT INTO option_set VALUES( 1, 2, NULL, 'b' );
sqlite> INSERT INTO option_set VALUES( 1, 3, NULL, 'c' );
sqlite> INSERT INTO option_set VALUES( 2, 1, NULL, 'd' );
sqlite> INSERT INTO option_set VALUES( 2, 2, NULL, 'e' );
sqlite> INSERT INTO option_set VALUES( 2, 3, 1, NULL );
sqlite> INSERT INTO option_set VALUES( 2, 4, NULL, 'f' );

这个想法是,在表的每一行中,我要么有一个值,要么应该扩展另一个set_id。问题是我不知道如何查询这样的表 - 我怎么能产生选项列表而不是递归地做选择?我并不是对包含和值列永远不会有效的结构感到疯狂,但不确定如何解决这个问题。不同的桌子设计会更好吗?

感谢。

1 个答案:

答案 0 :(得分:2)

要进行递归查询,您需要recursive common table expression

WITH RECURSIVE
  contained_sets(level, idx, contained_set_id, value)
  AS (SELECT 0, idx, contained_set_id, value
      FROM option_set
      WHERE set_id = 2
      UNION ALL
      SELECT level + 1,
             option_set.idx,
             option_set.contained_set_id,
             option_set.value
      FROM option_set
      JOIN contained_sets ON option_set.set_id = contained_sets.contained_set_id
      ORDER BY 1 DESC, 2)
SELECT value
FROM contained_sets
WHERE contained_set_id IS NULL;

value
----------
d
e
a
b
c
f

(这在SQLite 3.8.3或更高版本中受支持。)