我有如下的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查询,该查询将为我提供给定品牌或型号的每种资产类型的数量计数。
例如如果我想获取make ='am1'的每种资产类型的数量,
site_id | Container_qty | Cage_qty | Crate_qty
1 2 0 0
例如如果我想获取make ='cm1'的每种资产类型的数量,则结果集看起来像
site_id | Container_qty | Cage_qty | Crate_qty
1 0 0 3
我在下面编写了查询,以将'asset_type'行中的值转换为列,但是无法弄清楚如何基于字段'asset_ids_json'中的属性来过滤和汇总计数。可以肯定的是,asset_ids_json中的json数组的长度将始终与“ quantity”列中的值相同。
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。
答案 0 :(得分:1)
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_id
,asset_type
和quantity
数据感兴趣,所以可以使用DISTINCT
消除它们。 DISTINCT ON
检查每个id
的不同值。因此,如果两个JSON数组包含相同的键/值,则将两者都保存。