- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设我使用 ltree 存储了一棵树:
id | path | sort
------------------------------
0 |0 |1
1 |0.1 |2
2 |0.1.2 |3
3 |0.1.3 |1
4 |0.1.4 |2
5 |0.5 |3
6 |0.6 |1
我想选择节点以便:
像这样:
id | path | sort
------------------------------
0 |0 |1
6 |0.6 |1
1 |0.1 |2
3 |0.1.3 |1
4 |0.1.4 |2
2 |0.1.2 |3
5 |0.5 |3
第一个要求可以通过 ORDER BY path
实现,但我不知道如何实现第二个,这是否可能?
最佳答案
我正在用第二个 ltree sort_path
和一些触发器来解决这个问题。
最终,您将在 sort_path 树上排序,其值基于所有祖先的排序列的 lpad 加上当前行的排序列的 lpad。
id | path | rank | sort_path
--------------------------------------------
0 |0 |1 | 0001
6 |0.6 |1 | 0001.0001
1 |0.1 |2 | 0001.0002
3 |0.1.3 |1 | 0001.0002.0001
4 |0.1.4 |2 | 0001.0002.0002
2 |0.1.2 |3 | 0001.0002.0003
5 |0.5 |3 | 0001.0003
顺便说一句,即使您拥有的简单路径排序也不是很正确,一旦您遇到两位数的路径段,您就会遇到麻烦,因为路径排序是基于字母的,而不是数字。
请注意,完整的解决方案包括一个触发器,当任何父节点行的排序值发生更改时,它会重新计算所有后代的 sort_path 值。
示例实现:
CREATE EXTENSION IF NOT EXISTS ltree;
CREATE TABLE tree_nodes (path LTREE, rank INT, sort_path LTREE);
CREATE OR REPLACE FUNCTION calc_sort_path(tree_path LTREE, sibling_rank INT) RETURNS LTREE AS $$
DECLARE
sort_ranks TEXT[];
sort_path LTREE;
ancestor RECORD;
BEGIN
-- Default to the segment text (prepended with underscore).
-- If some ancestors are missing, this ensures the children will still sort together.
FOR iterator IN 1..NLEVEL(tree_path) LOOP
sort_ranks[iterator] := '_' || SUBPATH(tree_path, iterator-1, 1)::TEXT;
END LOOP;
-- Format a sort rank path segment for each ancestor.
FOR ancestor IN
SELECT NLEVEL(tree_nodes.path) AS level, tree_nodes.rank FROM tree_nodes
WHERE tree_nodes.path @> tree_path AND tree_nodes.path != tree_path
LOOP
sort_ranks[ancestor.level] := LPAD(ancestor.rank::TEXT, 4, '0');
END LOOP;
-- Format a final sort rank path segment for this leaf node.
sort_ranks[NLEVEL(tree_path)] := LPAD(sibling_rank::TEXT, 4, '0');
-- Convert array to LTREE path.
SELECT STRING_AGG(padded_rank, '.')::LTREE INTO sort_path FROM
(SELECT UNNEST(sort_ranks) AS padded_rank) path_ranks;
RETURN sort_path;
END
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION update_sort_paths() RETURNS trigger AS $$
DECLARE
has_changed BOOLEAN;
BEGIN
has_changed := TG_OP = 'UPDATE' AND (OLD.path IS DISTINCT FROM NEW.path OR OLD.rank IS DISTINCT FROM NEW.rank);
IF (TG_OP = 'DELETE' OR has_changed) THEN
UPDATE tree_nodes SET sort_path = calc_sort_path(path, rank) WHERE OLD.path @> path;
END IF;
IF (TG_OP = 'INSERT' OR has_changed) THEN
UPDATE tree_nodes SET sort_path = calc_sort_path(path, rank) WHERE NEW.path @> path;
END IF;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
DROP TRIGGER IF EXISTS on_rank_change ON tree_nodes;
CREATE TRIGGER on_rank_change AFTER INSERT OR UPDATE OR DELETE ON tree_nodes
FOR EACH ROW EXECUTE PROCEDURE update_sort_paths();
关于sql - 使用 PostgreSQL ltree 对节点进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49850810/
我有下表(简化): CREATE TABLE groups ( id PRIMARY KEY, path ltree, ... ); CREATE TABLE items ( id
我正在使用 PostgreSQL 和 ltree 构建大量二叉树数据。对于特定逻辑,我必须获取给定节点的最左/最右路径。 我的二叉树示例 我的表格内容示例 示例输入和预期输出: 输入 - 节点 1,最
我正在使用 PostgreSQL 和 ltree 构建大量二叉树数据。对于特定逻辑,我必须获取给定节点的最左/最右路径。 我的二叉树示例 我的表格内容示例 示例输入和预期输出: 输入 - 节点 1,最
我在使用 ltree 时遇到 PHP 问题来自 PostgreSQL .我在 SQL 中这样做: SELECT * FROM tabla t WHERE t.parent_path " for "OP
如何编写迁移文件以添加字段类型 'ltree' (PostgreSQL) Schema::create('table', function (Blueprint $table) { ....
我是 postgres 的新手,希望将 ltree 用于分层数据结构。 我在 varchar 列中同时拥有数据和 ltree 结构(即 domain.class.sublass),并且需要将 ltre
好的,所以我有一个表,其中 ltree 列在名为 path 的列上。我想选择多个路径,但我不想有大量的 OR 语句。这可能吗?或者这是最好的方法吗? 路径: 'schools.myschool.*'
我添加了 ltree 扩展,我可以在我的数据库中看到该扩展,但是当我运行以下查询时: CREATE TABLE flight_office.document_folder ( document_fol
正如标题所暗示的,我很难猜出如何有效地更新多行中的值。该列是使用数据类型 ltree 实现的。因此,在 postgresql 中应该有某种形式的特殊操作可用于此数据类型。这是一个示例: 表的名称,比方
我有一个库存表,它可以有一个树状的类别,比如: 计算机->PC计算机->平板电脑->Apple电子->计算机->其他 为此,ltree 模块看起来最合适。但是,它不能接受名称中的空格,例如“Perso
假设我使用 ltree 存储了一棵树: id | path | sort ------------------------------ 0 |0
我有一个包含 ltree 路径和名称列的 properties 表。 Ltree 路径包含父节点的 id,即“7968.7969.7987.8000”。每个树节点都有带有一些数值的报告。我需要找到 l
我一直在使用 Postgres ltree构造存储层次结构。现在,我想收集树中的所有叶节点。有没有一个简单的机制来做到这一点? CREATE TABLE foo AS SELECT node::l
我们使用 Postgres 中的 sql using ltree 来处理一些分层数据。 然而,当我们使用 cast 语法时,查询会非常慢,查询计划显示它实际上首先转换为 cstring,然后是 lqu
使用 Postgres ltree 存储产品类别的推荐方法是什么? 例如,我的专栏可能包含一个 ltree 路径,例如 "1.2.3",其中 1、2 和 3 是可以向用户显示的类别标签表的外键: ca
我计划实现一个使用 ltree 作为多级分类的数据库。但是,当我尝试获取路径 x 或 y 的条目时遇到了麻烦。 new_table +-------+--------+-------
我有 3 个表: LOCATION、LOCATION DESCRIPTION,其中包含每个位置的语言等,还有 1 个用于商店。 LOCATION DESCRIPTION 表还在 ltree 路径字段中
我在关系数据库中有一个表,我在其中使用称为 Materialized path 的技术对树进行编码(也称为沿袭列)。也就是说,对于我树中的每个节点,我在表中都有一行,对于每一行,我都有一个名为 anc
我正在考虑使用 PostgreSQL 的 Ltree module在我的应用程序中帮助线程评论。我一直在关注它以用于线程评论。我认为它会帮助您需要更新节点及其子节点的情况,例如当您想要隐藏评论及其回复
物化路径是一种在 SQL 中表示层次结构的方法。每个节点都包含路径本身及其所有祖先( grandparent/parent/self )。 MP ( docs ) 的 django-treebeard
我是一名优秀的程序员,十分优秀!