![](/img/trans.png)
[英]How to Use Group By clause when we use Aggregate function in the Joins?
[英]How to aggregate json fields when using GROUP BY clause in postgres?
我的 Postgres DB (v12.0) 中有以下表結構
id | pieces | item_id | material_detail
---|--------|---------|-----------------
1 | 10 | 2 | [{"material_id":1,"pieces":10},{"material_id":2,"pieces":20},{"material_id":3,"pieces":30}]
2 | 20 | 2 | [{"material_id":1,"pieces":40}
3 | 30 | 3 | [{"material_id":1,"pieces":20},{"material_id":3,"pieces":30}
我正在對這些記錄使用 GROUP BY 查詢,如下所示
SELECT SUM(PIECES) FROM detail_table GROUP BY item_id HAVING item_id =2
使用它我將獲得總件數為 30。但是我如何通過 material_id 從 material_detail 組中獲得總件數。
我想要這樣的結果
pieces | material_detail
-------| ------------------
30 | [{"material_id":1,"pieces":50},{"material_id":2,"pieces":20},{"material_id":3,"pieces":30}]
由於我來自 MySQL 背景,我不知道如何使用 Postgres 中的 JSON 字段來實現這一點。
注意: material_detail 列是 JSONB 類型。
您在兩個不同的級別上進行聚合。 我想不出不需要兩個單獨的聚合步驟的解決方案。 此外,要聚合材料信息,必須首先取消 item_id 的所有 arrays,然后才能為每個 material_id 聚合實際件值。 然后必須將其聚合回 JSON 數組。
with pieces as (
-- the basic aggregation for the "detail pieces"
select dt.item_id, sum(dt.pieces) as pieces
from detail_table dt
where dt.item_id = 2
group by dt.item_id
), details as (
-- normalize the material information and aggregate the pieces per material_id
select dt.item_id, (m.detail -> 'material_id')::int as material_id, sum((m.detail -> 'pieces')::int) as pieces
from detail_table dt
cross join lateral jsonb_array_elements(dt.material_detail) as m(detail)
where dt.item_id in (select item_id from pieces) --<< don't aggregate too much
group by dt.item_id, material_id
), material as (
-- now de-normalize the material aggregation back into a single JSON array
-- for each item_id
select item_id, jsonb_agg(to_jsonb(d) - 'item_id') as material_detail
from details d
group by item_id
)
-- join both results together
select p.item_id, p.pieces, m.material_detail
from pieces p
join material m on m.item_id = p.item_id
;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.