Суммарные значения, извлеченные из массива json на основе условия - PullRequest
0 голосов
/ 01 мая 2018

У меня есть поле JSON в таблице, как показано ниже

{
"Ui": [
    {
        "element": "TG1",
        "mention": "in",
        "time": 123
    },
    {
        "element": "TG1",
        "mention": "out",
        "time": 125
    },        
    { "element": "TG2",
        "mention": "in",
        "time": 251
    },
    {
        "element": "TG2",
        "mention": "out",
        "time": 259
    }
]
 }

Мое намерение - получить что-то вроде ниже

| element  |   Timespent   |
|  TG1     |     2         |
|  TG2     |     8         |

но были полностью неудачны. Как бы я получил разницу (сумма за все время, когда упоминание включено - сумма за все время, когда упоминание отсутствует)? В настоящее время я пытаюсь сделать sum(jsonb_extract_path(data::jsonb, 'ui','hovers')->0->'when'), чтобы получить сумму, но не могу понять, как рекурсивно заглянуть в файл json и отфильтровать его.

1 Ответ

0 голосов
/ 01 мая 2018

Используйте json_array_elements() для извлечения столбцов из массива json:

select value->>'element' as element, value->>'time' as time_spent
from my_table
cross join json_array_elements(json_column->'Ui')

 element | time_spent 
-----+------------
 TG1     | 123
 TG1     | 125
 TG2     | 251
 TG2     | 259
(4 rows)

Измените приведенный выше запрос, чтобы получить суммы в группах по элементам:

select element, sum(time) as time_spent
from my_table
cross join lateral (
  select
    value->>'element' as element,
    case value->>'mention' when 'in' then -(value->>'time')::numeric else (value->>'time')::numeric end as time
  from json_array_elements(json_column->'Ui')) as elements
group by 1
order by 1

 element | time_spent 
---------+------------
 TG1     |          2
 TG2     |          8
(2 rows)

DbFiddle.

...