【发布时间】:2022-01-19 11:54:59
【问题描述】:
我需要获取给定某个区域 ID 的所有子区域 ID。在表areas 中,有一个引用areas 表本身的parent_id 字段。现在可以有多个级别,例如,ID为1的区域可以是ID为2的区域的父级,而ID为2的区域可以是ID为3的区域的父级等等。所以当我调用这个函数时,我需要某个区域 id 的所有后代。
SELECT id, get_all_children(id) as children from areas where id = 1;
结果应该是
| id | children |
| -------- | -------------- |
| 1 | {2,3} |
这是我迄今为止尝试过的
CREATE OR REPLACE FUNCTION get_all_children(ancestors INT[])
RETURNS INT[]
LANGUAGE plpgsql
AS
$$
DECLARE
childrenRet INT[];
BEGIN
SELECT
ARRAY_AGG(id::INT) INTO childrenRet
FROM areas
WHERE parent_id = ANY(ancestors);
IF childrenRet = '{}' THEN
RETURN childrenRet;
END IF;
RETURN ARRAY_CAT(get_all_children(childrenRet), childrenRet);
END;
$$;
SELECT id, get_all_children(id) as children from areas where id = 492;
但我得到的结果是
| id | children |
| -------- | -------------- |
| 492 | {3044} |
我尝试将直接子级返回为
CREATE OR REPLACE FUNCTION get_all_children(ancestors INT[])
RETURNS INT[]
LANGUAGE plpgsql
AS
$$
DECLARE
childrenRet INT[];
BEGIN
SELECT
ARRAY_AGG(id::INT) INTO childrenRet
FROM areas
WHERE parent_id = ANY(ancestors);
RETURN childrenRet;
END;
$$;
SELECT id, get_all_children(id) as children from areas where id = 492;
我仍然得到相同的结果。
现在我试过了
SELECT ARRAY_AGG(id) FROM areas WHERE parent_id = 492;
这是我得到的结果
array_agg
------------------------------------------------------------------------------------
{3044,3075,923,1470,774,1466,1473,1468,1467,3043,1471,1469,922,1472,3076,1474,920}
我猜问题出在这里,但我不知道如何处理它。
SELECT
ARRAY_AGG(id::INT) INTO childrenRet
FROM areas
WHERE parent_id = ANY(ancestors);
【问题讨论】:
-
您的标题似乎具有误导性。您似乎可以很好地分配给该变量,即没有错误。您的问题在于您的函数返回的结果,因此请重命名您的问题以反映这一点。
-
如果分配正确,我应该得到一个包含所有直接子元素的数组,而不是只得到第一个元素。
-
我已经更新了答案,调整了您的程序和结果,以及一个小提琴链接。
标签: sql postgresql recursion plpgsql