Postgres:交叉表查询中的桶总是从左边开始填充

3

我的查询如下:

SELECT mthreport.*
FROM crosstab
('SELECT 
to_char(ipstimestamp, ''mon DD HH24h'') As row_name, 
varid::text || log.varid || ''_'' || ips.objectname::text As bucket, 
COUNT(*)::integer As bucketvalue
FROM loggingdb_ips_boolean As log 
INNER JOIN IpsObjects As ips 
ON log.Varid=ips.ObjectId
WHERE ((log.varid = 37551) 
OR (log.varid = 27087) 
OR (log.varid = 50876)
OR (log.varid = 45096)
OR (log.varid = 54708)
OR (log.varid = 47475)
OR (log.varid = 54606)
OR (log.varid = 25528)
OR (log.varid = 54729))
GROUP BY to_char(ipstimestamp, ''yyyy MM DD HH24h''), row_name, objectid, bucket        
ORDER BY to_char(ipstimestamp, ''yyyy MM DD HH24h''), row_name, objectid, bucket' )

As mthreport(item_name text,  varid_37551 integer, 
            varid_27087  integer , 
            varid_50876  integer , 
            varid_45096  integer , 
            varid_54708  integer , 
            varid_47475  integer , 
            varid_54606  integer , 
            varid_25528  integer , 
            varid_54729  integer , 
            varid_29469 integer)

查询可以通过以下连接字符串在测试表中进行测试: "host=bellariastrasse.com port=5432 dbname=IpsLogging user=guest password=guest"
该查询在语法上是正确的,可以正常运行。但问题在于 COUNT(*) 的值总是填充最左侧的列。然而,在许多情况下,左侧列应该为零或为空,并且只有第二(或第 n 个)列应该被填充。我的头脑已经混乱了,我无法弄清楚问题出在哪里!

1
我正在尝试连接psql,但出现了pg_hba.conf验证失败的问题。 - kgrittn
抱歉,我匆忙设置了访客账户,可能弄错了一些东西。我会在今天检查一下有什么问题。 - aag
连接应该已经修复了。你可以再试一次吗? - aag
1个回答

2
你的问题的解决方案是使用带有两个参数crosstab()变量。
第二个参数(另一个查询字符串)生成输出列的列表,以便在数据查询(第一个参数)中的NULL值被正确分配。
查看tablefunc扩展手册,特别是crosstab(text, text)
引用:

单参数形式的crosstab的主要限制是它将组中的所有值视为相同,将每个值插入到第一个可用列中。如果您希望值列对应于特定的数据类别,并且某些组可能没有某些类别的数据,则这不起作用。 crosstab的两个参数形式通过提供与输出列对应的类别的显式列表来处理此情况。

重点是我自己加的。我最近发布了一些相关答案hereherehere

谢谢Erwin,kiss-de-hoand gnä'herr(=“你是那个人”,大致翻译)!我将尝试使用双参数查询并回报! - aag
太棒了!我按照Erwin的指示设置了第二个查询,现在一切都像魔法般地运行!接下来,我将尝试使用函数来提供类别字段。在我看来,“函数”方式是一个不错的解决方法,可以生成“动态”交叉表,其类别可能事先未知。我是对的吗? - aag
1
@aag:“Küss die Hand gnä' Frau!”是老派维也纳的问候语,但实际上只针对女性——同性人群之间公开亲吻手没有在旧奥地利帝国时期流行。 :D - Erwin Brandstetter
@aag:关于动态函数:只有在返回类型相同的情况下才能这样做。否则,你将不得不返回具有未知列的记录——这会让你回到起点。 - Erwin Brandstetter
我仍然在尝试生成一个函数时遇到了很多麻烦。主要问题是如何从loggingdb_ips_boolean表中计算字段varid :: text || log.varid ||''_''|| ips.objectname :: text,并联接IpsObjects表的ObjectId字段。但我真的无法想出如何编写能够提取这些值的函数。你能帮我一下吗? - aag

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接