4

与えられた:{{1,"a"},{2,"b"},{3,"c"}}
望ましい:

 foo | bar
-----+------
  1  |  a
  2  |  b
  3  |  c

次のクエリで意図した結果を得ることができます。ただし、配列のサイズに合わせてスケーリングするものを用意することをお勧めします。

SELECT arr[subscript][1] as foo, arr[subscript][2] as bar
FROM  ( select generate_subscripts(arr,1) as subscript, arr
        from (select '{{1,"a"},{2,"b"},{3,"c"}}'::text[][] as arr) input 
      ) sub;
4

2 に答える 2

2

これは機能します:

select key as foo, value as bar
from json_each_text(
  json_object('{{1,"a"},{2,"b"},{3,"c"}}')
);

結果:

 foo | bar
-----+------
  1  |  a
  2  |  b
  3  |  c

ドキュメント

于 2015-10-28T23:27:27.490 に答える
1

Not sure what exactly you mean saying "it'd be better to have something that scales with the size of the array". Of course you can not have extra columns added to resultset as the inner array size grows, because postgresql must know exact colunms of a query before its execution (so before it begins to read the string).

But I would like to propose converting the string into normal relational representation of matrix:

select i, j, arr[i][j] a_i_j from (
 select i, generate_subscripts(arr,2) as j, arr from (
  select generate_subscripts(arr,1) as i, arr
  from (select ('{{1,"a",11},{2,"b",22},{3,"c",33},{4,"d",44}}'::text[][]) arr) input
 ) sub_i
) sub_j

Which gives:

i | j | a_i_j
--+---+------
1 | 1 | 1
1 | 2 | a
1 | 3 | 11
2 | 1 | 2
2 | 2 | b
2 | 3 | 22
3 | 1 | 3
3 | 2 | c
3 | 3 | 33
4 | 1 | 4
4 | 2 | d
4 | 3 | 44

Such a result may be rather usable in further data processing, I think.

Of course, such a query can handle only array with predefined number of dimensions, but all array sizes for all of its dimensions can be changed without rewriting the query, so this is a bit more flexible approach.

ADDITION: Yes, using with recursive one can build resembling query, capable of handling array with arbitrary dimensions. None the less, there is no way to overcome the limitation coming from relational data model - exact set of columns must be defined at query parse time, and no way to delay this until execution time. So, we are forced to store all indices in one column, using another array.

Here is the query that extracts all elements from arbitrary multi-dimensional array along with their zero-based indices (stored in another one-dimensional array):

with recursive extract_index(k,idx,elem,arr,n) as (
 select (row_number() over())-1 k, idx, elem, arr, n from (
  select array[]::bigint[] idx, unnest(arr) elem, arr, array_ndims(arr) n 
  from ( select '{{{1,"a"},{11,111}},{{2,"b"},{22,222}},{{3,"c"},{33,333}},{{4,"d"},{44,444}}}'::text[] arr ) input
 ) plain_indexed
union all
 select k/array_length(arr,n)::bigint k, array_prepend(k%array_length(arr,2),idx) idx, elem, arr, n-1 n 
 from extract_index
 where n!=1
)
select array_prepend(k,idx) idx, elem from extract_index where n=1

Which gives:

idx     | elem
--------+-----
{0,0,0} | 1
{0,0,1} | a
{0,1,0} | 11
{0,1,1} | 111
{1,0,0} | 2
{1,0,1} | b
{1,1,0} | 22
{1,1,1} | 222
{2,0,0} | 3
{2,0,1} | c
{2,1,0} | 33
{2,1,1} | 333
{3,0,0} | 4
{3,0,1} | d
{3,1,0} | 44
{3,1,1} | 444

Formally, this seems to prove the concept, but I wonder what a real practical use one could make out of it :)

于 2013-09-02T20:48:18.117 に答える