Postgres:使用Array进行“递归”查询

时间:2013-09-30 19:18:16

标签: sql arrays postgresql

我有一个数据库(我无法更改),一个表看起来像这样:

| ID:integer | fk:integer | next:[integer array] |
--------------------------------------------------
| 1          | 711        | {4}                  |
| 2          | 712        | {6}                  |
| 3          | 788        |                      |
| 4          | 799        | {7}                  |
--------------------------------------------------

现在我尝试定义一个Query作为第一行的数据ID = 1和下一行,所有数据ID都在整数数组next中{{{ 1}})以便我的查询返回:

{4}

然后停止,所以它只会导致元素具有指定的| ID:integer | fk:integer | next:[integer array] | -------------------------------------------------- | 1 | 711 | {4} | | 4 | 799 | {7} | -------------------------------------------------- 及其ID个元素。

我试过了......像这样,但我不能让它工作:

next

我使用的当前解决方法是首先使用此查询:

SELECT * FROM tablenm WHERE ID = ANY(SELECT next FROM tablenm WHERE ID = 1) AND ID = 1

然后对于Array中的每个元素,我以编程方式在循环中以SELECT * FROM tablenm WHERE ID = 1 运行相同的查询,但这看起来像一个脏黑客,我希望有一个SQL语句的解决方案。

2 个答案:

答案 0 :(得分:2)

这不需要递归,只需要数组取消嵌套。

这应该有效:

select * from tablename where id=1
UNION ALL
select * from tablename where id
  in (select unnest(next) from tablename where id=1);

答案 1 :(得分:2)

您可以在加入条件中使用= ANY(array)

SELECT t2.*
FROM   tbl t1
JOIN   tbl t2 ON t2.id = ANY(t1.next)
              OR t2.id = t1.id  -- add first row
WHERE  t1.id = 1                -- enter id to filter on once
ORDER  BY (t2.id <> t1.id);     -- "first row the data with ID = ?"

应该是最快的 正如@Daniel解释的那样,表单(与您的查询一样)仅包含第一行一次

如果您想要“更短的查询”:

SELECT t2.*
FROM   tbl t1
JOIN   tbl t2 ON t2.id = ANY(t1.next || t1.id) -- append id to array
WHERE  t1.id = 1;  -- not sure if you need ORDER BY

比第一种形式更短但不快,因为它将在内部扩展到与第一种形式相当的形式。使用EXPLAIN ANALYZE测试效果。

应该注意next甚至可以是NULL,因为:

SELECT NULL::int[] || 5  --> '{5}'