获取postgres中json数据数组列中元素的平均值

时间:2014-08-27 16:07:09

标签: sql arrays json postgresql amazon-redshift

我在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数据数组中获得平均零售价的建议吗?

1 个答案:

答案 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.