Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql Postgres:带数组的“递归”查询_Sql_Arrays_Postgresql - Fatal编程技术网

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%。