1

我有两个具有 1:M 关系的表,我想将此关系分组为 dict 或 JSON。

我的数据类似于:(id,provider_code,provider)

41108;2450;"provider1"
41108;1064389;"provider4"
41108;609920;"provider2"
41108;540582;"provider3"
41108;228268;"provider2"
41108;169483;"provider2"
41108;93361;"provider2"
41108;47723;"provider1"
41109;2658780;"provider4"
41109;62348;"provider1"
41109;320588;"provider3"
41109;323161;"provider3"
42500;;""

我正在寻找的是这样的:

41108;{"provider1":540582, "provider2":1064389, "provider3":228268, "provider3":93361};
41109;{"provider1":989301, "provider2":98536, "provider3":323161, "provider3":47854}

我不介意聚合是否为 JSON 格式,但我需要它易于解析。

我已经尝试过使用 postgres 函数 array_agg,但是虽然我已经解析为 varchar,但仍然出现错误:

ERROR:  function array_agg(character varying, character varying) does not exist

这是我正在尝试的查询,但我知道这是参数的问题,我需要一种方法来传递 2 个参数,而不是只传递一个。

select  id,  array_agg(code::varchar, id_provider::varchar)
from properties
full outer join providers 
on properties.id = providers.id 
group by id,  code, id_provider
order by id, code

表定义: 属性表:

"id";"integer"

提供者表:

"id";"integer"
"provider_code";"integer"
"provider";"character varying"
4

3 回答 3

1
SELECT id,
       CASE
          WHEN min(pv.provider) IS NULL
          THEN NULL::jsonb
          ELSE jsonb_agg(
                  jsonb_build_object(
                     COALESCE(pv.provider, ''),
                     pv.provider_code
                  )
               )
          END
FROM properties pp
   LEFT JOIN providers pv
      USING (id)
GROUP BY id;
于 2017-06-27T08:12:38.257 回答
1

您可以使用jsonb_build_object()为每个code/id_provider元组创建一个 json 对象,并用于jsonb_agg将它们聚合到一个 json 数组中:

WITH data(id, code, id_provider) AS (
  VALUES
    (41108,2450,'provider1'),
    (41108,1064389,'provider4'),
    (41108,609920,'provider2'),
    (41108,540582,'provider3'),
    (41108,228268,'provider2'),
    (41108,169483,'provider2'),
    (41108,93361,'provider2'),
    (41108,47723,'provider1'),
    (41109,2658780,'provider4'),
    (41109,62348,'provider1'),
    (41109,320588,'provider3'),
    (41109,323161,'provider3'),
    (42500,NULL,'')
)
SELECT id, jsonb_agg(jsonb_build_object(id_provider, code))
FROM data
GROUP BY id
;
┌───────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│  id   │                                                                                       jsonb_agg                                                                                       │
├───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 41109 │ [{"provider4": 2658780}, {"provider1": 62348}, {"provider3": 320588}, {"provider3": 323161}]                                                                                          │
│ 41108 │ [{"provider1": 2450}, {"provider4": 1064389}, {"provider2": 609920}, {"provider3": 540582}, {"provider2": 228268}, {"provider2": 169483}, {"provider2": 93361}, {"provider1": 47723}] │
│ 42500 │ [{"": null}]                                                                                                                                                                          │
└───────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
(3 rows)

如果您不想保留code IS NULL仅添加WHERE子句的行:

WITH data(id, code, id_provider) AS (
  VALUES
    (41108,2450,'provider1'),
    (41108,1064389,'provider4'),
    (41108,609920,'provider2'),
    (41108,540582,'provider3'),
    (41108,228268,'provider2'),
    (41108,169483,'provider2'),
    (41108,93361,'provider2'),
    (41108,47723,'provider1'),
    (41109,2658780,'provider4'),
    (41109,62348,'provider1'),
    (41109,320588,'provider3'),
    (41109,323161,'provider3'),
    (42500,NULL,'')
)
SELECT id, jsonb_agg(jsonb_build_object(id_provider, code))
FROM data
WHERE code IS NOT NULL
GROUP BY id
;
┌───────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│  id   │                                                                                       jsonb_agg                                                                                       │
├───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 41109 │ [{"provider4": 2658780}, {"provider1": 62348}, {"provider3": 320588}, {"provider3": 323161}]                                                                                          │
│ 41108 │ [{"provider1": 2450}, {"provider4": 1064389}, {"provider2": 609920}, {"provider3": 540582}, {"provider2": 228268}, {"provider2": 169483}, {"provider2": 93361}, {"provider1": 47723}] │
└───────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
(2 rows)
于 2017-06-27T07:59:16.693 回答
0

您可以尝试使用字符串连接运算符,然后按如下方式聚合:

select  properties.id, 
array_to_string(array_agg('{"' ||providers.provider || '": ' || providers.code || '}'), ',') as t
from properties
full outer join providers 
on properties.id = providers.id 
group by properties.id, providers.id
order by properties.id, t

请参阅以下 SQL 小提琴: 链接

于 2017-06-27T08:15:11.087 回答