将特定的数组项目放在一行(PostgreSQL)

时间:2012-02-17 14:41:20

标签: arrays postgresql

这是我的问题:

我有一个包含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中获取相应的值。

有没有办法为此获得解决方案?

2 个答案:

答案 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个元素。