这是我的问题:
我有一个包含4列(type = array,one-dimensional)的表,其值如下:
ID c1 c2 c3
1 {1, 2, 3} {10, 20, 30} {100, 200, 300}
2 {4, 5, 6} {11, 22, 33} {111, 222, 333}
我想知道是否有可能获得如下结果:
select ID, c1, c2, c3 from t1 where c3 = 200 (<---- pseudo-statement!)
结果:
1, 2, 20, 200
或
select ID, c1, c2, c3 from t1 where c3 = 333
结果:
1, 6, 33, 333
所以我想要的是在where-statement中获取相应的值。
有没有办法为此获得解决方案?
答案 0 :(得分:2)
(编辑1:简化,编辑2:更广泛的范围)
任何数组长度的解决方案。同样返回所有匹配,即使在一个或多个阵列中的多个位置同时也是如此。
如果您知道一维数组的固定长度,则可以在generate_series()
中对其进行硬编码,以获得最简单,最快速的解决方案:
SELECT id, c1[i], c2[i], c3[i]
FROM tbl, generate_series(1, 3) i
WHERE c3[i] = 200;
如果c3
中的所有数组都具有相同的未知长度,则可以以极低的成本进行推广:
SELECT id, c1[i], c2[i], c3[i]
FROM tbl, generate_subscripts((SELECT c3 FROM tbl LIMIT 1), 1) s(i)
WHERE c3[i] = 200;
请注意,我在这里使用方便的功能generate_subscripts()
对于比上限更大的下标,数组元素只是NULL
并且退出查询。
如果c3
中数组的未知长度实际上变化,您可以以更高的成本推广更多内容:
SELECT id, c1[i], c2[i], c3[i]
FROM tbl
FROM tbl, generate_series(1, (SELECT max(array_upper(c3, 1)) FROM tbl)) s(i)
WHERE c3[i] = 200;
最后,对于非标准数组下标,此外可以这样做:
SELECT id, c1[i], c2[i], c3[i]
FROM tbl
, generate_subscripts((SELECT c3 FROM tbl
ORDER BY array_length(c3,1) DESC LIMIT 1), 1) s(i)
WHERE c3[i] = 200;
WITH tbl (id, c1, c2, c3) AS (
VALUES
(1, '{1, 2, 3}'::int[], '{10, 20, 30}'::int[], '{100, 200, 300}'::int[])
,(2, '{4, 5, 6}', '{11, 22, 33}', '{111, 222, 333}')
-- un-comment to test 333 in all positions of c3 and varying array length
-- ,(3, '{7, 8, 9, 10}', '{14, 25}', '{333, 333, 333, 333}')
)
SELECT id, c1[i], c2[i], c3[i]
FROM tbl
,generate_subscripts((SELECT c3 FROM tbl
ORDER BY array_length(c3,1) DESC LIMIT 1), 1) s(i)
WHERE c3[i] = 333;
答案 1 :(得分:1)
你需要使用generate_series来生成表的交叉连接和数组的所有索引(这里它将是1,2,3):
select *
from (
select yourtab.id
, yourtab.c1[tidx.idx]
, yourtab.c2[tidx.idx]
, yourtab.c3[tidx.idx]
from yourtab
cross join generate_series(1, 3) tidx(idx)
) t(id, c1, c2, c3)
where c3 = 333
请注意,每个数组总是有3个元素。