我在Postgres中存储AdWords报告数据。每个报告都存储在一个名为Reports的表中,该表有一个名为' data'的jsonb列。每个报告都将json存储在其“数据”中。看起来像这样的字段:
[
{
match_type: "exact",
search_query: "gm hubcaps",
conversions: 2,
cost: 1.24
},
{
match_type: "broad",
search_query: "gm auto parts",
conversions: 34,
cost: 21.33
},
{
match_type: "phrase",
search_query: "silverdo headlights",
conversions: 63,
cost: 244.05
}
]
我想要做的是查询这些数据哈希并总结给定报告的总转化次数。我看过Postgresql文档,看起来你只能对哈希进行计算,而不是像这样的哈希数组。是我在postgres中尝试做的事情吗?我需要从这个数组中创建一个临时表并进行计算吗?或者我可以使用存储过程吗?
我正在使用Postgresql 9.4
修改 我不仅仅使用常规的规范化表格的原因是,这只是报告数据结构的一个示例。在我的项目中,报告必须允许任意密钥,因为用户使用他们喜欢的任何列上传CSV来填充它们。它基本上只是一种绕过任意多个用户创建的表的方法。
答案 0 :(得分:1)
您可以使用unnest
:
select sum(conv) from
(select d->'conversion' as conv from
(select unnest(data) as d from <your table>) all_data
) all_conv
免责声明:我没有Pg 9.2,所以我自己无法测试。
编辑:假设您提到的数组是Postgresql数组,即data
列的数据类型为character varying[]
。如果您的意思是data
是一个json数组,那么您应该可以使用json_array_elements
而不是unnest
。
答案 1 :(得分:1)
我想要做的是查询这些数据哈希值并总结转化次数
最快的方式应该是jsonb_populate_recordset()
。但是你需要一个注册的行类型。
CREATE TEMP TABLE report_data (
-- match_type text -- commented out, because we only need ..
-- , search_query text -- .. conversions for this query
conversions int
-- , cost numeric
);
临时表是注册行类型ad-hoc的一种方法。在这个相关答案中有更多解释:
假设缺少信息的表report
report_id
为PK。
SELECT r.report_id, sum(d.conversions) AS sum_conversions
FROM report r
LEFT JOIN LATERAL jsonb_populate_recordset(null::report_data, r.data) d ON true
-- WHERE r.report_id = 12345 -- only for given report?
GROUP BY 1;
LEFT JOIN
确保您获得结果,即使data
为NULL或为空或JSON数组为空。
对于基础表中单行的总和,这更快:
SELECT d.sum_conversions
FROM report r
LEFT JOIN LATERAL (
SELECT sum(conversions) AS sum_conversions
FROM jsonb_populate_recordset(null::report_data, r.data)
) d ON true
WHERE r.report_id = 12345; -- enter report_id here
替代jsonb_array_elements()
(不需要注册的行类型):
SELECT d.sum_conversions
FROM report r
LEFT JOIN LATERAL (
SELECT sum((value->>'conversions')::int) AS sum_conversions
FROM jsonb_array_elements(r.data)
) d ON true
WHERE r.report_id = 12345; -- enter report_id here
通常你会把它作为普通的规范化表来实现。我没有看到JSON的好处(除了您的应用程序似乎需要它,就像您添加的那样)。