仅当存在一对值时,Postgres 才会对 json 中的值求和
Postgres sum values from json only if pair of values exist
我的 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": "TG2",
"mention": "in",
"time": 251
}
]
}
我正在尝试获取每个元素的时间差总和,如下所示
| element | Timespent |
| TG1 | 2 |
| TG2 | 8 |
理想情况下,每个 "in" 元素都应该有一个 "out" 元素,但在上面的示例中显然不是这种情况。我只想计算这对值的差值,而忽略任何没有对应输出到输入的值。我该怎么做?
下面是我用来获取时差的
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
我不确定你的 json_column 属性 - 你需要按它分组以避免行之间的值混合,所以我将它包含在 CTE 部分的 window 聚合中。但是你的结果中没有它,所以我在最后的 qry 中也跳过了它。简而言之 - 您可以检查订单号是否为偶数且等于最大订单号,然后跳过它:
select json_column
, e->>'element' element
, case when
mod(lag(i) over (partition by json_column::text ,e->>'element' order by i),2) = 0
and
max(i) over (partition by json_column::text ,e->>'element') = i
then true else false end "skip"
, case when e->>'mention' = 'in' then -(e->>'time')::int else (e->>'time')::int end times
from my_table, json_array_elements(json_column->'Ui') with ordinality o(e,i)
)
select element, sum (times)
from logic
where not skip
group by element
;
element | sum
---------+-----
TG1 | 2
TG2 | 8
(2 rows)
我的 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": "TG2",
"mention": "in",
"time": 251
}
]
}
我正在尝试获取每个元素的时间差总和,如下所示
| element | Timespent |
| TG1 | 2 |
| TG2 | 8 |
理想情况下,每个 "in" 元素都应该有一个 "out" 元素,但在上面的示例中显然不是这种情况。我只想计算这对值的差值,而忽略任何没有对应输出到输入的值。我该怎么做?
下面是我用来获取时差的
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
我不确定你的 json_column 属性 - 你需要按它分组以避免行之间的值混合,所以我将它包含在 CTE 部分的 window 聚合中。但是你的结果中没有它,所以我在最后的 qry 中也跳过了它。简而言之 - 您可以检查订单号是否为偶数且等于最大订单号,然后跳过它:
select json_column
, e->>'element' element
, case when
mod(lag(i) over (partition by json_column::text ,e->>'element' order by i),2) = 0
and
max(i) over (partition by json_column::text ,e->>'element') = i
then true else false end "skip"
, case when e->>'mention' = 'in' then -(e->>'time')::int else (e->>'time')::int end times
from my_table, json_array_elements(json_column->'Ui') with ordinality o(e,i)
)
select element, sum (times)
from logic
where not skip
group by element
;
element | sum
---------+-----
TG1 | 2
TG2 | 8
(2 rows)