这些查询中的每一个都适用于单个 id 以及整个表。
您也可以只返回路径/完整路径或所有其他列。
SELECT t.*, concat_ws('->', t1.path, t.name) AS full_path
FROM tbl t
LEFT JOIN LATERAL (
SELECT string_agg(t1.name, '->' ORDER BY i) AS path
FROM generate_subscripts(t.arrayofparents, 1) i
JOIN tbl t1 ON t1.id = t.arrayofparents[i]
) t1 ON true
WHERE t.id = 4; -- optional
或者,您可以将 移动ORDER BY
到子查询 - 可能会快一点:
SELECT concat_ws('->', t1.path, t.name) AS full_path
FROM tbl t, LATERAL (
SELECT string_agg(t1.name, '->') AS path
FROM (
SELECT t1.name
FROM generate_subscripts(t.arrayofparents, 1) i
JOIN tbl t1 ON t1.id = t.arrayofparents[i]
ORDER BY i
) t1
) t1
WHERE t.id = 4; -- optional
由于聚合发生在LATERAL
子查询中,我们不需要GROUP BY
外部查询中的步骤。
我们也不需要LEFT JOIN LATERAL ... ON true
保留所有arrayofparents
为 NULL 或空的行,因为由于聚合函数,LATERAL
子查询总是返回一行。
LATERAL
需要 Postgres 9.3。
用于concat_ws()
忽略串联中可能的 NULL 值。
SQL小提琴。
WITH OTDINALITY
在 Postgres 9.4中让它变得更简单和更快:
SELECT t.*, concat_ws('->', t1.path, t.name) AS full_path
FROM tbl t, LATERAL (
SELECT string_agg(t1.name, '->' ORDER BY ord) AS path
FROM unnest(t.arrayofparents) WITH ORDINALITY a(id,ord)
JOIN tbl t1 USING (id)
) t1
WHERE t.id = 4;
详细解释:
UNION ALL
第 9.3 页的变体
SELECT t1.full_path
FROM tbl t, LATERAL (
SELECT string_agg(name, '->') AS full_path
FROM (
(
SELECT name
FROM generate_subscripts(t.arrayofparents, 1) i
JOIN tbl ON id = t.arrayofparents[i]
ORDER BY i
)
UNION ALL SELECT t.name
) t1
) t1
WHERE t.id = 4;