1
CREATE TABLE sectors
(
    sector_id integer PRIMARY KEY,
    sector_name varchar(100) NOT NULL,
    parent_sector_id integer REFERENCES sectors(sector_id)
);

INSERT INTO sectors(sector_id, sector_name, parent_sector_id)
SELECT 1, 'All sectors', NULL UNION ALL
SELECT 2, 'Business', 1 UNION ALL
SELECT 3, 'Manufacturing', 2 UNION ALL
SELECT 4, 'Retail', 2 UNION ALL
SELECT 5, 'Trading', 1 UNION ALL
SELECT 6, 'Nonprofit', 1 UNION ALL
SELECT 7, 'Agriculture', 1;

问题一:通过函数查找父级关系

SELECT is_parent(1/*All sectors*/, 4/*Retail*/) should be true
SELECT is_parent(2/*Business*/, 4/*Retail*/) should be true

问题2:通过函数查找子关系

SELECT is_child(4/*Retail*/, 1/*All sectors*/) should be true
SELECT is_child(4/*Retail*/, 2/*Business*/) should be true

对此的任何帮助将不胜感激。

4

2 回答 2

3

如果你真的需要回答这类查询,我建议你看看PostgreSQL's recursive queriesis_parent如果您需要实际编写这些函数( , )是某种家庭作业,is_child我还建议您使用递归查询来实现它们。

于 2011-06-26T15:28:58.840 回答
2

添加到巴勃罗的回应......

使用递归查询is_parent()非常快。假设你有一个索引parent_sector_id,你基本上每个深度级别都会进行一次索引扫描。

is_child()相比之下,如果您以幼稚的方式实现它并拥有一棵巨大的树,也就是不要抓住所有子节点并检查您的节点,将会非常缓慢。

如果您有这样的树并且偶尔需要检索所有子树,那么一个不错的选择是实现预排序树算法(使用浮点数或数字;而不是整数,因为它们会极大地减慢写入速度)或嵌套间隔。

如果没有,只需反转参数并调用is_parent(),即 sql 函数is_child(a, b)将返回is_parent(b, a)

最后但并非最不重要的一点是,您可能想要查看 contrib 中的ltree 数据类型。使用它,您可以使用任意节点上的 gist 索引执行 is_parent/is_child 查询。

于 2011-06-26T20:13:10.833 回答