繁体   English   中英

将单列中的JSON的postgres数组扩展为多个记录

[英]Expand a postgres array of JSON within a single column into multiple records

我有一个称为goals的表,其中每行包含1个目标。 有关目标特定指标的数据存储在JSON的ARRAY中,名为goal_metrics 有时有1个度量,有时有0个度量,其他时候有多个度量。 我想将所有目标指标提取到一个新表中,每个指标有1行,并且该指标所属的原始goal_id。

这是table1当前的样子:

+---------+------------+----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| goal_id | goal_owner | goal_create_at |                                                                                                                                                                                                             goal_metrics                                                                                                                                                                                                             |
+---------+------------+----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|   69660 |     148191 |     1566576355 | [{'metric_owner': '148191', 'metric_create_at': '1566576374', 'metric_target': '10'}, {'metric_owner': '148191', 'metric_create_at': '1566576403', 'metric_target': '1'}, {'metric_owner': '148191', 'metric_create_at': '1566576428', 'metric_target': '3'}, {'metric_owner': '148191', 'metric_create_at': '1566576450', 'metric_target': '3'}]                                                                                    |
|   68443 |     146270 |     1565911160 | [{'metric_owner': '144534', 'metric_create_at': '1565911175', 'metric_target': '1'}, {'metric_owner': '144352', 'metric_create_at': '1565911191', 'metric_target': '1'}, {'metric_owner': '144352', 'metric_create_at': '1565911212', 'metric_target': '15'}, {'metric_owner': '146270', 'metric_create_at': '1565911353', 'metric_target': '23'}]                                                                                   |
|   68440 |     146270 |     1565910356 | [{'metric_owner': '144061', 'metric_create_at': '1565910380', 'metric_target': '3'}, {'metric_owner': '144061', 'metric_create_at': '1565910462', 'metric_target': '0'}, {'metric_owner': '144534', 'metric_create_at': '1565910523', 'metric_target': '1'}, {'metric_owner': '143866', 'metric_create_at': '1565911422', 'metric_target': '6'}]                                                                                     |
|   68442 |     146270 |     1565910746 | [{'metric_owner': '143866', 'metric_create_at': '1565910863', 'metric_target': '9'}, {'metric_owner': '143866', 'metric_create_at': '1565910881', 'metric_target': '1'}, {'metric_owner': '144534', 'metric_create_at': '1565910905', 'metric_target': '1'}, {'metric_owner': '146270', 'metric_create_at': '1565910927', 'metric_target': '1'}, {'metric_owner': '144534', 'metric_create_at': '1565910956', 'metric_target': '1'}] |
+---------+------------+----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

这就是我想要达到的目标:

+--------------+------------------+---------------+---------+
| metric_owner | metric_create_at | metric_target | goal_id |
+--------------+------------------+---------------+---------+
|       143321 |       1557774894 |            56 |   53513 |
|       143321 |       1557774933 |           100 |   53513 |
|       143321 |       1557774983 |            10 |   53513 |
|       143321 |       1557775102 |           100 |   53513 |
|       143321 |       1557775388 |           100 |   53513 |
|       148191 |       1566576374 |            10 |   69660 |
|       148191 |       1566576403 |             1 |   69660 |
|       148191 |       1566576428 |             3 |   69660 |
|       148191 |       1566576450 |             3 |   69660 |
|       144534 |       1565911175 |             1 |   68443 |
|       144352 |       1565911191 |             1 |   68443 |
|       144352 |       1565911212 |            15 |   68443 |
|       146270 |       1565911353 |            23 |   68443 |
|       144061 |       1565910380 |             3 |   68440 |
|       144061 |       1565910462 |             0 |   68440 |
|       144534 |       1565910523 |             1 |   68440 |
|       143866 |       1565911422 |             6 |   68440 |
|       143866 |       1565910863 |             9 |   68442 |
|       143866 |       1565910881 |             1 |   68442 |
|       144534 |       1565910905 |             1 |   68442 |
|       146270 |       1565910927 |             1 |   68442 |
|       144534 |       1565910956 |             1 |   68442 |
+--------------+------------------+---------------+---------+

如果它只是常规的JSON列,则可以使用SELECT goal_metric -> 'metrics_owner' AS metrics_owner ,但是由于它是可变长度的数组,因此无法使用。 我认为我需要使用JSON_TO_RECORDSET ,并且已经在尝试进行此操作,但是我仍无法实现所需的功能。

有多种可能的方式( Postgres JSON文档 ):

演示:分贝<>小提琴


答:使用json_array_elements()

SELECT
    goal_id,
    (elems ->> 'metric_owner')::int AS metric_owner,
    (elems ->> 'metric_create_at')::int AS metric_create_at,
    (elems ->> 'metric_target')::int AS metric_target
FROM
    table1,
    json_array_elements(goal_metrics) as elems

这会将每个数组元素扩展为一行。 可以查询这些扩展的JSON对象的属性。 这给出了text类型。 如果希望它们为int类型,则需要强制转换。


B:使用json_to_recordset()

SELECT
    goal_id,
    elems.*
FROM
    table1,
    json_to_recordset(goal_metrics) 
        AS elems(metric_owner int, metric_create_at int,metric_target int)

这一步与(A)中的步骤相同。 您只需要定义输出类型。


C:如果必须定期执行此操作,一次定义输出类型可能很有用。 然后可以在json_populate_recordset()使用它:

CREATE TYPE metrics_type 
    AS (metric_owner int, metric_create_at int,metric_target int);

SELECT
    goal_id,
    elems.*
FROM
    table1,
    json_populate_recordset(null::metrics_type, goal_metrics) AS elems
first un nest and give a try with ->> option

 with basejson  as (select goal_id ,goal_owner,unnest(goal_metrics) goal_metrics  from jsonmetrics ) select goal_id, goal_owner,goal_metrics->>'metric_owner' "MstricOwner",goal_metrics->>'metric_target' "MetricTGT"  from basejson;
 goal_id | goal_owner | MstricOwner | MetricTGT 
---------+------------+-------------+-----------
       4 |          1 | 143866      | 9
       2 |          2 | 143866      | 9
       2 |          2 | 143867      | 9


暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM