标签: tree

使用 SQL 遍历关系数据库中的树状数据

有没有办法在 SQL 中遍历树数据?我知道connect by在 Oracle 中,但是在其他 SQL 实现中还有另一种方法吗?我问是因为使用connect by比编写循环或递归函数来为每个结果运行查询更容易。

由于有些人似乎对短语“树数据”感到困惑,我将进一步解释:我的意思是关于具有parent_id或类似字段的表,该字段包含来自同一表中另一行的主键。

问题来自我在 Oracle 数据库中处理以这种方式存储的数据的经验,并且知道connect by其他 DBMS 中没有实现。如果要使用标准 SQL,则必须为每个想要向上的父表创建一个新表别名。这很容易失控。

tree hierarchy feature-comparison

16
推荐指数
3
解决办法
7764
查看次数

如何构建模型以正确有效地表示关系数据库上的树状数据?

基于Traversing tree-like data in arelational database using SQL问题,我想知道如何在考虑物理含义的情况下经常使用的方式描述关系数据库上的树状数据?

我假设 RDBMS 除了常规 SQL ANSI 或常见可用功能之外没有特殊功能来处理它。

毫无疑问,我总是对 MySQL 和 PostgreSQL 以及最终的 SQLite 感兴趣。

tree erd database-design relational-theory

13
推荐指数
2
解决办法
1720
查看次数

COUNT 行的父 id 等于我们在一个查询中父 id 为 0 的行

我想使用 MySQL 在一个查询中执行以下操作:

  • 抓取一个 parent_id 为 0 的行
  • 抓取我们抓取的具有 parent_id 为 0 的行的 parent_id 的所有行的计数

如何在一个查询中完成此操作?如果您需要更多信息,请告诉我,我很乐意为您提供帮助。我不是创建问题的专家,所以请告诉我您需要什么更多信息。

这是我现在正在做的一个例子:

select id from messages where parent_id=0
Run Code Online (Sandbox Code Playgroud)

进而

select count(id) from messages where parent_id={{previously_chosen_id}}
Run Code Online (Sandbox Code Playgroud)

如何获得一次性查询?就像是...

select id, count(records where parent_id=the id we just asked for)
Run Code Online (Sandbox Code Playgroud)

或者,有没有更好的方法来处理这个问题?你看,目前我必须运行大量查询才能找到计数,而我宁愿一次性完成。

mysql tree hierarchy

10
推荐指数
1
解决办法
3万
查看次数

从事决策树数据库设计

我正在做决策树数据库的概念模型。目标是存储任何决策树。

我有四种实体类型:DecisionTree、Node、Branch 和 Leaf。

  • 每个决策树由决策节点、分支和叶子组成。
  • 每个决策节点都有一个名称和位置。
  • 每个分支都是可能的决策或事件的路径。
  • 每个叶子都有代表待分类对象的类标签。

决策树示例:

在此处输入图片说明

图 1 提供了一个决策树及其相关规则的示例,其中 p(Class #i) 是对象属于 Class #i 的概率。

SQL 数据库中的树示例:

决策树的表示:

在此处输入图片说明

我的概念设计在以下实体关系图 (ERD) 中表示:

在此处输入图片说明

所以,问题是:如何将节点、分支和叶与决策树关联起来?

tree erd database-design

8
推荐指数
0
解决办法
2819
查看次数

PostgreSQL 树结构和递归 CTE 优化

我试图在 PostgreSQL (8.4) 中表示树结构,以便能够查询从根到给定节点的路径或查找子分支中的所有节点。

下面是一个测试表:

CREATE TABLE tree_data_1 (
    forest_id TEXT NOT NULL,
    node_id TEXT NOT NULL,
    parent_id TEXT,
    node_type TEXT,
    description TEXT,
    PRIMARY KEY (forest_id, node_id),
    FOREIGN KEY (forest_id, parent_id) REFERENCES tree_data_1 (forest_id, node_id)
);
CREATE INDEX tree_data_1_forestid_parent_idx ON tree_data_1(forest_id, parent_id);
CREATE INDEX tree_data_1_forestid_idx ON tree_data_1(forest_id);
CREATE INDEX tree_data_1_nodeid_idx ON tree_data_1(node_id);
CREATE INDEX tree_data_1_parent_idx ON tree_data_1(parent_id);
Run Code Online (Sandbox Code Playgroud)

每个节点由(forest_id, node_id)(在另一个林中可以有另一个具有相同名称的节点)标识。每棵树都从一个根节点(其中parent_id为空)开始,尽管我只希望每个森林都有一个。

这是使用递归 CTE 的视图:

CREATE OR REPLACE VIEW tree_view_1 AS
    WITH RECURSIVE rec_sub_tree(forest_id, node_id, parent_id, depth, path, cycle) …
Run Code Online (Sandbox Code Playgroud)

postgresql performance tree optimization cte

6
推荐指数
1
解决办法
5641
查看次数

建模层次属性

我正在尝试找出零售商的数据模型。

该零售商在全国拥有多家商店,它们使用以下层次结构进行建模:

Channel -> Zone -> City -> Store
Run Code Online (Sandbox Code Playgroud)

每家商店都包含几篇文章。每篇文章都有这样的属性

  • 激活标志(这表明文章的存在)
  • 价钱
  • 供应商
  • 仓库

现在,零售商可以在层次结构中的任何级别设置这些属性。考虑以下情况:

  • 在渠道级别为商品设置价格将应用于所有商店。
  • 设置在更高级别的价格可以在任何其他级别被覆盖。例如,在城市级别仅针对城市中的商店或特定商店。
  • 这适用于上面列出的所有属性。

到目前为止,他们已经使用 RDBMS 对其进行建模,方法是在层次结构的顶部定义全局规则,并将异常作为单独的行单独调用。比如说,价格表将在渠道级别为文章设置价格,任何级别的任何更改都将单独指定。显然,这在获取商店级别的属性时效率不高。

样本数据

假设 Channel、Zone、City 和 Store 统称为实体。频道的 ID 范围 >= 4000,区域 >= 3000,城市 >= 2000,商店范围从 1 到 1000。

下面给出了层次关系数据的一个子集:

Channel   | Zone     | City    | Store |
----------+----------+------------------
4001      | 3001     | 2001    | 13    |
4001      | 3001     | 2001    | 14    |
4001      | 3001     | 2002    | 15    |
4001      | 3002     | 2003    | 16    | …
Run Code Online (Sandbox Code Playgroud)

tree database-design hierarchy

5
推荐指数
1
解决办法
969
查看次数

对于每个类别,使用 PostgreSQL 递归 CTE 查找所有子类别中外键项的计数

我在 PostgreSQL 9.4 中存储了一个典型的树结构作为邻接列表:

gear_category (
   id INTEGER PRIMARY KEY,
   name TEXT,
   parent_id INTEGER   
);
Run Code Online (Sandbox Code Playgroud)

以及附加到类别的项目列表:

gear_item (
   id INTEGER PRIMARY KEY,
   name TEXT,
   category_id INTEGER REFERENCES gear_category
);
Run Code Online (Sandbox Code Playgroud)

任何类别都可以附加装备物品,而不仅仅是树叶。

出于速度原因,我想预先计算有关每个类别的一些数据,我将使用这些数据来生成物化视图。

期望的输出:

speedy_materialized_view (
   gear_category_id INTEGER,
   count_direct_child_items INTEGER,
   count_recursive_child_items INTEGER
);
Run Code Online (Sandbox Code Playgroud)

count_recursive_child_items是附加到当前类别或任何子类别的 GearItems 的累积数量。每个类别应占一行,任何为 0 的计数都为 0。

为了计算这个,我们需要使用递归 CTE 来遍历树:

WITH RECURSIVE children(id, parent_id) AS (
    --base case
    SELECT gear_category.id AS id, gear_category.parent_id AS parent_id
    FROM gear_category
    WHERE gear_category.id = 37  -- setting this to id includes current object …
Run Code Online (Sandbox Code Playgroud)

postgresql tree cte count

5
推荐指数
1
解决办法
1995
查看次数

如何最好地将目录树存储在数据库中?

我想以某种格式表示我的目录结构(目前我只是使用 JSON。)

这是示例 JSON 的外观。对于那些好奇的人,它是使用 unix tree 命令生成的:tree /path/to/folder -J --noreport -h.

{
    ...
    "type":"directory",
    "name":"dev",
    "size":4096,
    "contents":[
        {"type":"directory","name":"protocols","size":4096, "contents":[]},
        {"type":"file","name":"architecture.txt","size":4716},
        {"type":"file","name":"exceptions.py","size":31263},
        {"type":"file","name":"models.js","size":101882},
        {"type":"file","name":"proxy.cpp","size":29097},
        {"type":"file","name":"keylogfile.xyz","size":7889},
        {"type":"file","name":"Readme.txt","size":8857},
    ]
    ...
}
Run Code Online (Sandbox Code Playgroud)

所以这只是将某些路径的整个文件夹结构表示为 JSON。

我可以有许多这样的单独 JSON 文件,每个文件代表一个目录树。这些文件之间没有关联/链接。

在标准 Windows“C:\”分区上运行 tree 命令时,我得到一个大约 30 MB 的 JSON 文件。所以我认为我们可以假设用户上传的最大文件大小约为 100 MB。


存储文件后,这些是我计划对文件进行的操作:

  1. 获取整个文件。
  2. 给定一条路径,获取它的直接子项(类似于ls在这条路径上做的事情。)
  3. 给定路径,获取路径的完整子树。
  4. 修改某个项目的元数据,比如更改其名称或添加新的名称note

2 和 3 是我最希望发生的操作。


以下是我提出的存储这些数据的方法:

  1. 没有数据库:

    • 将文件按原样存储在磁盘 ( /home/forest/<uuid>.json)
    • 操作 1 变得快速而简单 - 只需发送整个文件
    • 但其他的可能会变慢,因为它们都涉及首先解析整个 JSON,然后对其进行迭代。
  2. 没有 SQL

    • 我以前从未使用过任何 SQL 数据库(只阅读了一些关于它们的用例等的帖子) …

tree database-design

5
推荐指数
1
解决办法
8007
查看次数

可以用三级 B 树索引的最大记录数是多少?B+树?

我正在学习动态树结构组织以及如何设计数据库。

考虑具有以下特征的 DBMS:

  • 大小为 2048 字节的文件页
  • 12 字节的指针
  • 56 字节的页头

二级索引定义在 8 字节的页面上。可以用三级 B 树索引的最大记录数是多少?并且具有三级 B+树?

以下是这些树的两个示例:

B树

B+树

我的尝试

B+树

我读过那个

B+树比B树。因为除了最后一个之外,每个叶节点中只有表示为k最高键的集合存储在非叶节点中,组织为 B 树。关系 DBMS 内部,第 5 章:动态树结构组织,第 46 页

因此有一个区别,我们存储在 B 树的节点中的东西存储在 B+ 树的叶子中。因此,在我看来,它是(m-1) hm是顺序,h是高度),因为每个节点最多包含另一个节点的 (m-1) 个键。但这与字节数无关。

然而我在上面提到的书中找到了下表:

树的最小最大高度根据页面的大小

因此它会是 20 3.7条记录吗?

B树

对于他们来说,只要有一些值存储在节点中,我就必须除以节点数。而我被困在那里。

index tree database-size btree max

5
推荐指数
1
解决办法
3432
查看次数

PostgreSQL - 检索树中给定子节点的所有 ID

我有一个客户的非二叉树,我需要为给定节点获取树中的所有 ID。

该表非常简单,只是一个带有父ID和子ID的连接表。这是我存储在数据库中的树的表示。

在此处输入图片说明

在这个例子中,如果我搜索节点 17,我需要返回 14-17。如果我搜索 11,我需要返回 1-6-5-4-8-11-12-7-2-10-3。

顺序并不重要。在将子节点添加到节点时,我只需要 ID 以避免循环。

我创建了这个查询。祖先部分工作正常,我检索了所有父节点,但对于后代我有一些麻烦。我只能检索树的某些部分。例如,对于节点 11,我检索 4-10-6-11-7-8,因此树的所有正确部分都丢失了。

WITH RECURSIVE
-- starting node(s)
starting (parent, child) AS
(
  SELECT t.parent, t.child
  FROM public.customerincustomer AS t
  WHERE t.child = :node or t.parent = :node
)
,
ancestors (parent, child) AS
(
  SELECT t.parent, t.child
  FROM public.customerincustomer AS t
  WHERE t.parent IN (SELECT parent FROM starting)
  UNION ALL
  SELECT t.parent, t.child
  FROM public.customerincustomer AS t JOIN ancestors AS a ON t.child = a.parent
),
descendants (parent, …
Run Code Online (Sandbox Code Playgroud)

postgresql tree recursive

5
推荐指数
2
解决办法
3637
查看次数