column values as column names in thepsql query

后端 未结 1 351
清歌不尽
清歌不尽 2021-01-24 07:42

Based on this I have a table which has values which will be the column names of the PostgreSQL query result.

id    col1     col2
----------------------
0      na         


        
相关标签:
1条回答
  • 2021-01-24 08:08

    For PostgreSQL 9.4+

    -- Test data
    create table t(id int, col1 text, col2 text);
    insert into t values
      (0, 'name', 'ax'),
      (0, 'name2', 'bx'),
      (0, 'name3', 'cx'),
      (1, 'name', 'dx'),
      (1, 'name2', 'ex'),
      (1, 'name3', 'fx');
    
    create or replace function fn_pivot(
      p_sql text,
      p_row_field text,
      p_col_field text,
      p_data_field text,
      p_cursor refcursor) returns refcursor language plpgsql as $$
    declare
      cols text[];
      a text[];
      q text;
      --f text;
    begin
      -- Get dynamic columns
      q := format('select array_agg(distinct %s::text) from (%s) t', p_col_field, p_sql);
      execute q into cols;
      -- Generate SELECT part
      select array_agg(format('%s filter (where %s::text = %L) as %I', p_data_field, p_col_field, x, x)) into a from unnest(cols) as t(x);
      q := format('%s, %s', p_row_field, array_to_string(a, ', '));
      -- Complete the whole statement
      q := format('select %s from (%s) t group by %s order by %s', q, p_sql, p_row_field, p_row_field);
      raise info '%', q;
      open p_cursor for execute q;
      return p_cursor;
    end $$;
    

    Usage (with some debug output):

    nd@postgres=# start transaction;
    START TRANSACTION
    *nd@postgres=# select * from fn_pivot('select * from t', 'id', 'col1', 'max(col2)', 'cur');
    INFO:  select id, max(col2) filter (where col1::text = 'name') as name, max(col2) filter (where col1::text = 'name2') as name2, max(col2) filter (where col1::text = 'name3') as name3 from (select * from t) t group by id order by id
    ╔══════════╗
    ║ fn_pivot ║
    ╠══════════╣
    ║ cur      ║
    ╚══════════╝
    (1 row)
    
    *nd@postgres=# fetch all in cur;
    ╔════╤══════╤═══════╤═══════╗
    ║ id │ name │ name2 │ name3 ║
    ╠════╪══════╪═══════╪═══════╣
    ║  0 │ ax   │ bx    │ cx    ║
    ║  1 │ dx   │ ex    │ fx    ║
    ╚════╧══════╧═══════╧═══════╝
    (2 rows)
    
    *nd@postgres=# rollback;
    
    0 讨论(0)
提交回复
热议问题