json - Postgres - 如何从 JSON 列中搜索和聚合

标签 json postgresql pivot aggregate-functions

我有一个 asset_quantities 表如下

id   |   asset_type   |    quantity   |    site_id   |   asset_ids_json
  1      'Container'           3              1             [{"id":1,"make":"am1","model":"amo1"},{"id":2,"make":"am1","model":"amo2"},{"id":3,"make":"am3","model":"amo3"}]
  2      'Cage'                3              1             [{"id":4,"make":"bm1","model":"bmo1"},{"id":5,"make":"bm2","model":"bmo2"},{"id":6,"make":"bm2","model":"cmo3"}]
  3      'Crate'               3              1             [{"id":7,"make":"cm1","model":"cmo1"},{"id":8,"make":"cm1","model":"cmo1"},{"id":9,"make":"cm1","model":"cmo2"}]

我想在 Postgres 中编写一个 SQL 查询,它将为我提供给定品牌或型号的每种 Assets 类型的数量。

例如如果我想获取每个 Assets 类型的数量,其中 make='am1',

site_id   |   Container_qty    |     Cage_qty     |     Crate_qty
   1               2                     0                  0

例如如果我想获取每个 Assets 类型的数量,其中 make='cm1',结果集看起来像

site_id   |   Container_qty    |     Cage_qty     |     Crate_qty
   1               0                     0                  3

我编写了下面的查询以将“asset_type”行中的值转换为列,但无法弄清楚如何根据“asset_ids_json”字段中的属性过滤和聚合计数。可以安全地假设 asset_ids_json 中的 json 数组的长度将始终与“数量”列中的值相同。

select
  aq.site_id, 
  sum(case when aq.asset_type = 'Container' then aq.quantity end) container_qty,
  sum(case when aq.asset_type = 'Cage' then aq.quantity end) cage_qty ,
  sum(case when aq.asset_type = 'Crate' then aq.quantity end) crate_qty,
from asset_quantities aq
group by aq.site_id;

我的问题的关键是如何根据 json 列“asset_ids_json”中的属性过滤和聚合结果。我正在使用 Postgres 9.4。

最佳答案

step-by-step demo:db<>fiddle

SELECT
    site_id,
    SUM(case when asset_type = 'Container' then quantity end) container_qty,
    SUM(case when asset_type = 'Cage' then quantity end) cage_qty ,
    SUM(case when asset_type = 'Crate' then quantity end) crate_qty
FROM (
    SELECT DISTINCT ON (id)
        site_id,
        asset_type,
        quantity
    FROM asset_quantities aq,
        json_array_elements(asset_ids_json)
    WHERE value ->> 'make' = 'cm1'
) s
GROUP BY site_id

要在 JSON 数组的内容上获取 WHERE 子句,您必须扩展该数组。 json_array_elements() 为每个元素创建一行。这样就可以要求某个值。

由于这种扩展,当前行数成倍增加(这里是三倍,因为数组中有三个元素)。因为您只对简单复制到新记录中的原始 site_idasset_typequantity 数据感兴趣,所以您可以使用不同的DISTINCT ON 检查每个 id 的不同值。因此,如果两个 JSON 数组包含相同的键/值,则两者都将被保存。

关于json - Postgres - 如何从 JSON 列中搜索和聚合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56459674/

相关文章:

javascript - 在使用 Redux 进行 React 时,如何在从我的商店/状态中删除项目后更新我的 View

sql - 努力将数据集从行旋转到列

python - 尝试将网页中的JS数据输出到.html输出文件中

javascript - 创建自定义 json 对象

sql - 在 postgresql 中插入 ... 值(SELECT ... FROM ...)?

sql - 如何将多个选择的结果合并为一行

tsql - T-SQL - 交叉应用到 PIVOT? (将数据透视表与表值函数一起使用)?

php - 在 Javascript 中循环遍历 JSON 数组

将 elisp unixtime 转换为 js-date 对象

python-3.x - Postgres、sqlalchemy 和多处理