[英]Postgres: “Recursive” query with Array
I have a database (that I can't change) one table looks like that: 我有一个数据库(无法更改),一个表如下所示:
| ID:integer | fk:integer | next:[integer array] |
--------------------------------------------------
| 1 | 711 | {4} |
| 2 | 712 | {6} |
| 3 | 788 | |
| 4 | 799 | {7} |
--------------------------------------------------
Now I try to define one Query that as first row the data with ID = 1
and as next rows, all data with the ID
that are in the integer array next
( {4}
) so that my query returns: 现在我尝试定义一个查询,作为第一行与数据
ID = 1
个作为下一个行,与所有的数据ID
是整数数组中next
( {4}
使得我的查询返回:
| ID:integer | fk:integer | next:[integer array] |
--------------------------------------------------
| 1 | 711 | {4} |
| 4 | 799 | {7} |
--------------------------------------------------
But then stops, so it only results the element with the specified ID
and it's next
elements. 但是随后停止,因此它只会生成具有指定
ID
的元素及其next
元素。
I tried sth. 我尝试过…… like this, but I can't get it to work:
像这样,但我无法使它工作:
SELECT * FROM tablenm WHERE ID = ANY(SELECT next FROM tablenm WHERE ID = 1) AND ID = 1
The current Workaround I use is to first use this query: 我当前使用的解决方法是首先使用此查询:
SELECT * FROM tablenm WHERE ID = 1
And then for each element in the Array I run the same query with the ID
s in a loop programmatically, but this looks like a dirty hack and I hope there is a solutions for this with 1 SQL statement. 然后,对于数组中的每个元素,我都以编程方式在循环中运行
ID
s的相同查询,但这看起来像是一堆肮脏的东西,我希望有1条SQL语句可以解决此问题。
This doesn't require recursion, just array un-nesting. 这不需要递归,只需取消数组嵌套即可。
This should work: 这应该工作:
select * from tablename where id=1
UNION ALL
select * from tablename where id
in (select unnest(next) from tablename where id=1);
You can use = ANY(array)
in the JOIN condition: 您可以在JOIN条件中使用
= 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 = ?"
Should be fastest. 应该最快。
As @Daniel explained, this form (like your query) includes the first row only once . 作为@Daniel解释说, 这种形式(如您的查询)包括只有一次的第一行。
If you want a "shorter query": 如果要“更简短的查询”:
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
Shorter, but not faster than the first form, because this will be expanded to an equivalent of the first form internally. 比第一种形式更短但不快,因为它将在内部扩展为第一种形式的等效形式。 Test performance with
EXPLAIN ANALYZE
. 用
EXPLAIN ANALYZE
测试性能。
It should be noted that next
can even be NULL
, because: 应该注意,
next
甚至可以为NULL
,因为:
SELECT NULL::int[] || 5 --> '{5}'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.