我在postgres表中有一些数据,它是json数据数组的字符串表示形式,如下所示:
[
{"UsageInfo"=>"P-1008366", "Role"=>"Abstract", "RetailPrice"=>2, "EffectivePrice"=>0},
{"Role"=>"Text", "ProjectCode"=>"", "PublicationCode"=>"", "RetailPrice"=>2},
{"Role"=>"Abstract", "RetailPrice"=>2, "EffectivePrice"=>0, "ParentItemId"=>"396487"}
]
这是我数据库中一列相似数据的一个单元格中的数据。
db中存储的数据类型是varchar(max)。
我的目标是找到每个json项目的平均RetailPrice,其中包含“Role”=>“Abstract”,包括数组中的所有json元素以及数据库中的所有行。
类似的东西:
SELECT avg(json_extract_path_text(json_item, 'RetailPrice'))
FROM (
SELECT cast(json_items to varchar[]) as json_item
FROM my_table
WHERE json_extract_path_text(json_item, 'Role') like 'Abstract'
)
现在,显然这个特定的查询不会因某些原因而起作用。 Postgres不允许您直接将varchar转换为varchar []。即使我有一个数组,这个查询也无法迭代数组。它也可能存在其他问题,但我希望有助于澄清我想要得到的内容。
有关如何从数据库中的所有这些json数据数组中获得平均零售价的建议吗?
答案 0 :(得分:1)
Redshift似乎不支持json
数据类型本身。至少,I found nothing in the online manual.
但是我找到了一些JSON function in the manual,这应该是有用的:
JSON_ARRAY_LENGTH
JSON_EXTRACT_ARRAY_ELEMENT_TEXT
JSON_EXTRACT_PATH_TEXT
由于不支持generate_series()
,我们必须替换它......
SELECT tbl_id
, round(avg((json_extract_path_text(elem, 'RetailPrice'))::numeric), 2) AS avg_retail_price
FROM (
SELECT *, json_extract_array_element_text(json_items, pos) AS elem
FROM (VALUES (0),(1),(2),(3),(4),(5)) a(pos)
CROSS JOIN tbl
) sub
WHERE json_extract_path_text(elem, 'Role') = 'Abstract'
GROUP BY 1;
我用一个穷人的解决方案代替:一个从0到n(VALUES
表达式)计数的虚拟表。确保计算到阵列中可能元素的最大数量。如果您需要定期创建一个实际的numbers
表。
Modern Postgres有更好的选择,例如json_array_elements()
来取消json
数组。与你对Postgres的兄弟问题相比:
我在Postgres中用related operator ->>
测试了它的工作原理:
SQL Fiddle.