【问题标题】:How to creating dynamic columns using data PostgreSQL 9.1?如何使用数据 PostgreSQL 9.1 创建动态列?
【发布时间】:2014-08-23 19:39:59
【问题描述】:

首先,我对数据库和学习完全陌生。我有一个来自 puppetdb 的表,其中我使用 postgresql 作为后端。每个 certname 大约有 65 到 70 个值(可以随自定义事实增长),我的表如下所示:

表名:certname_facts

  certname       name          value
 ------------------------------------
  node1          kernel        Linux
  node1          memorysize    1.96 GB
  node1          osfamily      Debian
  node1          netmask eth0  255.255.255.0
      .             .             . 
      .             .             .
      .             .             .
  node2          kernel        Windows
  node2          memorysize    2.16 GB
  node2          osfamily      Windows
  node2          netmask eth0  255.255.255.0
      .             .             . 
      .             .             .
      .             .             .

我能够使用此链接创建视图:Automatically creating pivot table column names in PostgreSQL

create or replace function pivotcode (tablename varchar, rowc varchar, colc varchar,     cellc varchar, celldatatype varchar) returns varchar language plpgsql as $$
declare
   dynsql1 varchar;
   dynsql2 varchar;
   columnlist varchar;
begin

dynsql1 = 'select string_agg(distinct ''_''||'||colc||'||'' '||celldatatype||''','','' order by ''_''||'||colc||'||'' '||celldatatype||''') from '||tablename||';';
execute dynsql1 into columnlist;
dynsql2 = 'select * from crosstab (''select '||rowc||','||colc||','||cellc||' from '||tablename||' group by 1,2 order by 1,2'', ''select distinct '||colc||' from '||tablename||' order by 1'')

as newtable ('||rowc||' varchar,'||columnlist||');';
return dynsql2;
end
$$


--output of table
certname   kernel      memorysize   osfamily   netmask eth0   . . .
------------------------------------------------------------------------
node1      Linux       1.96 GB      Debian     255.255.255.0   . . .
node2      Windows     2.16 GB      Windows    255.255.255.0   . . . 

我遇到的问题是,有时某些节点没有相同的参数,并且参数可能会增长。

  certname       name          value
  -----------------------------------------
  node1          kernel        Linux
  node1          memorysize    1.96 GB
  node1          osfamily      Debian
  node1          netmask eth0  255.255.255.0
  node1          location       home
      .             .             .
  node2          kernel        Windows
  node2          memorysize    2.16 GB
  node2          osfamily      Windows
  node2          netmask eth0  255.255.255.0

  node3         kernel          linux
  node3         osfamily        Ubuntu
  node3         netmask eth0  255.255.255.0

所以当我去访问它失败的视图。关于如何处理这种情况的任何建议。有没有办法使视图完全动态并根据数据进行更改。我目前正在研究触发器和动态 sql 作为选项。


这是使用新的 dynsql2 语句更新后创建的函数的输出。

select * from crosstab ('select a.certname, a.colname, b.value from ( select certname,colname from (select distinct certname) left join columns on 1=1) a left join(select certname as certname,nameas col name ,value value from certname_facts group by 1,2 ) b on a.certname = b.certname and a.colname = b.colname) a','select distinct name from certname_facts order by 1') as newtable (certname varchar,_architecture varchar,_augeasversion varchar,_clientcert varchar,_clientversion varchar,_domain varchar,_environment varchar,_facterversion varchar,_fqdn varchar,_hardwareisa varchar,_hardwaremodel varchar,_hostname varchar,_id varchar,_interfaces varchar,_ipaddress_eth0 varchar,_ipaddress_lo varchar,_ipaddress varchar,_is_virtual varchar,_kernelmajversion varchar,_kernelrelease varchar,_kernel varchar,_kernelversion varchar,_lsbdistcodename varchar,_lsbdistdescription varchar,_lsbdistid varchar,_lsbdistrelease varchar,_lsbmajdistrelease varchar,_macaddress_eth0 varchar,_macaddress varchar,_manufacturer varchar,_memoryfree varchar,_memorysize varchar,_memorytotal varchar,_netmask_eth0 varchar,_netmask_lo varchar,_netmask varchar,_network_eth0 varchar,_network_lo varchar,_operatingsystemrelease varchar,_operatingsystem varchar,_osfamily varchar,_path varchar,_physicalprocessorcount varchar,_processor0 varchar,_processorcount varchar,_productname varchar,_ps varchar,_puppetversion varchar,_rubysitedir varchar,_rubyversion varchar,_selinux varchar,_serialnumber varchar,_sshdsakey varchar,_sshecdsakey varchar,_sshrsakey varchar,_swapfree varchar,_swapsize varchar,__timestamp varchar,_timezone varchar,_type varchar,_uniqueid varchar,_uptime_days varchar,_uptime_hours varchar,_uptime_seconds varchar,_uptime varchar,_virtual varchar);

【问题讨论】:

  • 如果您发布创建此代码的代码会很有帮助...但是您想要做的是创建您期望的列列表,然后左连接到您的数据...这会产生当该证书名的列不存在时为空。和我想的一样:stackoverflow.com/questions/8490478/…
  • It fails?请添加逐字错误消息。此外,缺少实际的视图定义以及您的 Postgres 版本。这个相关的答案可能会有所帮助:stackoverflow.com/questions/15506199/…
  • RROR: FROM 中的子查询必须有别名 LINE 1: ...name, b.value from ( select certname,colname from (select di... ^ 提示:例如,FROM (SELECT ...) [AS] foo.QUERY: select a.certname, a.colname, b.value from (select certname,colname from (select distinct certname) left join columns on 1=1) a left join(select certname as certname,nameas col name ,value value from certname_facts group by 1,2 ) b on a.certname = b.certname and a.colname = b.colname) a ********** Error **** ******
  • 对上述问题进行了更新
  • 此函数定义似乎与错误消息的类型和查询不匹配。此外,您还没有显示导致它的函数调用。请给出函数定义、函数调用和错误消息,包括所有匹配的查询。

标签: sql database postgresql dynamic postgresql-9.1


【解决方案1】:

我觉得这将是一个正在进行的类型的答案,需要进行大量更新才能使其正确。这样做也可能有更好的方法,但这应该可行。您需要在这里接受这个想法并为您的示例定制它......

将重点放在设置初始数据的交叉表查询行(而不是列列表):

'select * from crosstab (''select '||rowc||','||colc||','||cellc||' from '||tablename||' group by 1,2 order by 1,2''...

我们想要更改此语句,以便如果未找到列,则为该列返回空值。

这里有一定程度的伪代码:

select * from (select distinct certname) left join columns on 1=1

(列是您之前构建的列列表)

此交叉连接查询提供证书名称列表和您希望填充的列。现在将此处的列表加入 dynqry2 语句中的值。

(我提前道歉,这是上面提供的动态内容和我自己的伪代码的奇怪代码合并。您必须找到一种方法将 dynsql2 设置为该语句):

select a.certname, a.colname, b.value 
from ( select certname,colname 
    from (select distinct certname)
     left join columns on 1=1) a
left join
     (select '||rowc||' as certname,'||colc||'as col name ,'||cellc||' value 
     from '||tablename||' group by 1,2 ) b
on a.certname = b.certname and a.colname = b.colname) a

将其插入到 dynqry2 语句中的第一个交叉表参数中并试一试...

【讨论】:

    【解决方案2】:

    双参数交叉表对 cellc/value 使用 NULL,其中给定的 rowc/certname 在 tablename/certname_facts 中没有 colc/name 行。 (即,它执行 LEFT JOIN,如您的查询输出所示。)请参阅 F.36.1.4. crosstab(text, text) 示例。

    dynsql2 = '
        select * from crosstab (
            ''select '||rowc||','||colc||','||cellc||'
              from '||tablename||'
              order by 1'',
            ''select distinct '||colc||'
              from '||tablename||'
              order by 1''
        )
        as ('||rowc||' varchar,'||columnlist||')
        ';
    

    columnlist 中的 order 必须与 select distinct 中的相同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-28
      • 2014-01-24
      • 1970-01-01
      • 1970-01-01
      • 2019-07-20
      • 1970-01-01
      相关资源
      最近更新 更多