Postgres联合查询循环

时间:2019-02-04 19:14:46

标签: sql arrays postgresql

我有一个有两列的表。叫他们 array_columntext_column

我正在尝试编写一个查询,以找出K的范围从1到10,text_column中的值出现在array_column的前K个元素中有多少行

我期望的结果是:

k    |    count
________________
1    |    70
2    |    85
3    |    90
...

我确实通过简单地重复查询10次并将结果统一来获得这些结果,如下所示:

SELECT 1 AS k, count(*) FROM table WHERE array_column[1:1] @> ARRAY[text_column]
UNION ALL
SELECT 2 AS k, count(*) FROM table WHERE array_column[1:2] @> ARRAY[text_column]
UNION ALL
SELECT 3 AS k, count(*) FROM table WHERE array_column[1:3] @> ARRAY[text_column]
...

但这似乎不是正确的方法。如果我想要很大的K范围怎么办?

所以我的问题是,是否可以循环执行查询,并合并每个查询的结果?或者,如果这不是解决问题的正确方法,您将如何处理?

谢谢!

2 个答案:

答案 0 :(得分:2)

您可以使用array_positions()返回在数组中找到参数的所有位置的数组,例如

select t.*, 
       array_positions(array_column, text_column)
from the_table t;

这将返回不同的结果,但是效率更高,因为您无需增加结果的整体大小。只考虑前十个数组元素,只需将一个切片传递给函数:

select t.*, 
       array_positions(array_column[1:10], text_column)
from the_table t;

要将结果限制为仅包含实际值的行,您可以使用:

select t.*, 
       array_positions(array_column[1:10], text_column)
from the_table t
where text_column = any(array_column[1:10]);

要获得所需的结果,可以使用unnest()将其变成行:

select k, count(*)
from the_table t, unnest(array_positions(array_column[1:10], text_column)) as k
where text_column = any(array_column[1:10])
group by k
order by k;

答案 1 :(得分:1)

您可以使用generate_series函数生成具有期望值的期望行数的表,然后在查询中将其联接到表中,如下所示:

SELECT t.k AS k, count(*) 
FROM table 
--right join ensures that you will get a value of 0 if there are no records meeting the criteria
right join (select generate_series(1,10) as k) t 
 on array_column[1:t.k] @> ARRAY[text_column]
group by t.k

这可能是最接近使用循环遍历结果而不使用PL / SQL之类的东西在用户定义的函数中执行实际循环的事情。