我有一个有两列的表。叫他们
array_column
和text_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范围怎么办?
所以我的问题是,是否可以循环执行查询,并合并每个查询的结果?或者,如果这不是解决问题的正确方法,您将如何处理?
谢谢!
答案 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之类的东西在用户定义的函数中执行实际循环的事情。