使用SQLite创建列表树

问题描述 投票:8回答:2

我正在尝试使用PHP和SQLite表设置创建一个分层列表,如下所示:

    |   itemid  |   parentid    |   name    |
    -----------------------------------------
    |   1       |   null        |   Item1   |
    |   2       |   null        |   Item2   |
    |   3       |   1           |   Item3   |
    |   4       |   1           |   Item4   |
    |   5       |   2           |   Item5   |
    |   6       |   5           |   Item6   |

这些列表将使用无序列表构建,并允许这种类型的树结构:

Item1
    |_Item3
    |_Item4
Item2
    |_Item5
        |_Item6

我已经看到这对目录和平面数组完成了,但我似乎无法使其正常使用此结构并且没有深度限制。

php sqlite hierarchical-data
2个回答
13
投票

您正在使用教科书设计将分层数据存储在SQL数据库中。此设计称为邻接列表,即层次结构中的每个节点都有一个parentid外键到其直接父节点。

使用此设计,您无法生成类似于您描述的树并支持树的任意深度。你已经弄明白了。

大多数其他SQL数据库(PostgreSQL,Microsoft,Oracle,IBM DB2)都支持递归查询,从而解决了这个问题。但是SQLite和MySQL还不支持SQL的这个功能。

所以你需要另一个解决方案来存储层次结构。有几种解决方案。有关说明和示例,请参阅我的演示文稿Models for Hierarchical Data with PHP and MySQL

我通常更喜欢我称之为Closure Table的设计,但每种设计都有优点和缺点。哪一个最适合您的项目取决于您需要哪些类型的查询来有效地处理您的数据。所以你应该去研究解决方案并为自己选择一个。


0
投票

我知道这是在日志时间之前被问到的,但是使用当前的SQLite版本,它是微不足道的,并且不需要级别深度,因为@ Bill-Karwin说。所以应该重新考虑正确的答案:)

我的表有MCTMPLID和REF_TMPLID列,我的结构起始节点叫做ROOT

CREATE TABLE MyStruct (
  `TMPLID` text,
  `REF_TMPLID` text
);

INSERT INTO MyStruct
  (`TMPLID`, `REF_TMPLID`)
VALUES
  ('Root', NULL),
  ('Item1', "Root"),
  ('Item2', "Root"),
  ('Item3', 'Item1'),
  ('Item4', 'Item1'),
  ('Item5', 'Item2'),
  ('Item6', 'Item5');

这是构建树结构的主要查询

WITH RECURSIVE
  under_root(name,level) AS (
    VALUES('Root',0)
    UNION ALL
    SELECT tmpl.TMPLID, under_root.level+1
      FROM MyStruct as tmpl JOIN under_root ON tmpl.REF_TMPLID=under_root.name
     ORDER BY 2 DESC
  )
SELECT substr('....................',1,level*3) || name as TreeStructure FROM under_root

这是结果

Root
...Item1
......Item3
......Item4
...Item2
......Item5
.........Item6

我确信这可以修改为OP的表结构,所以让这个样本作为起点文档和一些样本https://www.sqlite.org/lang_with.html#rcex1

© www.soinside.com 2019 - 2024. All rights reserved.