Sql Postgres:带数组的“递归”查询
我有一个无法更改的数据库,其中一个表如下所示:Sql Postgres:带数组的“递归”查询,sql,arrays,postgresql,Sql,Arrays,Postgresql,我有一个无法更改的数据库,其中一个表如下所示: | ID:integer | fk:integer | next:[integer array] | -------------------------------------------------- | 1 | 711 | {4} | | 2 | 712 | {6} | | 3 | 788
| ID:integer | fk:integer | next:[integer array] |
--------------------------------------------------
| 1 | 711 | {4} |
| 2 | 712 | {6} |
| 3 | 788 | |
| 4 | 799 | {7} |
--------------------------------------------------
现在,我尝试定义一个查询,将ID=1的数据作为第一行,将ID为{4}的整数数组中的所有数据作为下一行,以便我的查询返回:
| ID:integer | fk:integer | next:[integer array] |
--------------------------------------------------
| 1 | 711 | {4} |
| 4 | 799 | {7} |
--------------------------------------------------
但随后停止,因此它只会生成具有指定ID的元素及其下一个元素
我试过这样的东西,但没法用:
SELECT * FROM tablenm WHERE ID = ANY(SELECT next FROM tablenm WHERE ID = 1) AND ID = 1
我当前使用的解决方法是首先使用此查询:
SELECT * FROM tablenm WHERE ID = 1
然后,对于数组中的每个元素,我以编程方式使用循环中的ID运行相同的查询,但这看起来像是一个肮脏的黑客行为,我希望有一个解决方案,使用1个SQL语句 这不需要递归,只需要数组取消嵌套 这应该起作用:
select * from tablename where id=1
UNION ALL
select * from tablename where id
in (select unnest(next) from tablename where id=1);
这不需要递归,只需要数组取消嵌套 这应该起作用:
select * from tablename where id=1
UNION ALL
select * from tablename where id
in (select unnest(next) from tablename where id=1);
您可以在连接条件中使用:
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 = ?"
较短,但不比第一个表单快,因为这将在内部扩展为第一个表单的等效项。使用解释分析测试性能
应该注意,next甚至可以为NULL,因为:
SELECT NULL::int[] || 5 --> '{5}'
您可以在连接条件中使用:
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 = ?"
较短,但不比第一个表单快,因为这将在内部扩展为第一个表单的等效项。使用解释分析测试性能
应该注意,next甚至可以为NULL,因为:
SELECT NULL::int[] || 5 --> '{5}'
您需要研究递归CTE;我会模拟一个例子,但我现在需要去买些食物;如果您有另一行,如id=7,next={somthing},您是否也需要将其放入resultset?我的意思是,这是真的递归还是只有两个级别?不,只有两个级别,Daniels的答案对我来说,可以取消数组的测试;我会模拟一个例子,但我现在需要去买些食物;如果您有另一行,如id=7,next={somthing},您是否也需要将其放入resultset?我的意思是,这是真正的递归还是只有两个级别?不,只有两个级别,Daniels的答案对我来说对数组进行了取消测试。谢谢,UNNEST完成了这个技巧,让它稍微短了一点:从tablename中选择*id=1,或者从tablename中选择UNNESTnext中的id id,其中id=1是。请注意,如果next的元素中恰好包含1,那么它将引入一个差异。在本例中,UNION ALL专门用于两次输出id=1行,而OR只会生成一次。感谢UNNEST完成了这项任务,使它稍微短了一点:从tablename中选择*,其中id=1,或从tablename中选择UNNESTnext中的id,其中id=1是。请注意,如果next的元素中恰好包含1,那么它将引入一个差异。在这种情况下,UNION ALL专门用于两次输出id=1行,而OR只会生成一次。谢谢,我测试了速度,它比另一个解决方案快约25%。谢谢,我测试了速度,它比另一个解决方案快约25%。