将PostgreSQL中的jsonb转换为无循环的行

时间:2018-12-22 12:08:43

标签: postgresql

ff我在我的postgres数据库中存储了一个json数组。第一个表格“订单”如下所示:

order_id, basket_items_id
1, {1,2}
2, {3}
3, {1,2,3,1}

第二个表“项目”如下所示:

item_id, price
1,5
2,3
3,20

已经尝试使用多个SQL加载数据并选择不同的jsonb记录,但这不是灵丹妙药。

SELECT
sum(price)
FROM orders
INNER JOIN items on
orders.basket_items_id = items.item_id
WHERE order_id = 3;

想要得到它作为输出:

order_id, basket_items_id, price
1, 1, 5
1, 2, 3
2, 3, 20
3, 1, 5
3, 2, 3
3, 3, 20
3, 1, 5

或者这个:

order_id, sum(price)
1, 8
2, 20
3, 33

2 个答案:

答案 0 :(得分:1)

您的orders.basket_items_id列是jsonb还是int[]类型?

如果类型为jsonb,则可以使用this post展开列:

SELECT
    o.order_id,
    o.basket_item_id,
    items.price
FROM
(
    SELECT
        order_id,
        jsonb_array_elements_text(basket_items_id)::int basket_item_id
    FROM
        orders
) o
JOIN
    items ON o.basket_item_id = items.item_id
ORDER BY
    1, 2, 3;

请参见json_array_elements_text

如果类型为int[](整数数组),则可以使用this DB-Fiddle函数运行类似的查询:

SELECT
    o.order_id,
    o.basket_item_id,
    items.price
FROM
(
    SELECT
        order_id,
        unnest(basket_items_id) basket_item_id
    FROM
        orders
) o
JOIN
    items ON o.basket_item_id = items.item_id
ORDER BY 
    1, 2, 3;

请参见unnest

答案 1 :(得分:1)

demo:db<>fiddle

SELECT
    o.order_id,
    elems.value::int as basket_items_id,
    i.price
FROM
    orders o, jsonb_array_elements_text(basket_items_id) as elems
LEFT JOIN items i 
ON i.item_id = elems.value::int
ORDER BY 1,2,3
  1. jsonb_array_elements_text将jsonb数组扩展为每个元素一行。有了这个,您就可以直接加入第二张桌子了
  2. 由于扩展数组为您提供了text个元素,因此您必须使用::int将它们转换为整数

当然,您也可以GROUPSUM进行汇总:

SELECT
    o.order_id,
    SUM(i.price)
FROM
    orders o, jsonb_array_elements_text(basket_items_id) as elems
LEFT JOIN items i 
ON i.item_id = elems.value::int
GROUP BY o.order_id
ORDER BY 1