Hai*_* Qu 9 arrays postgresql json jsonb
通过使用jsonb_array_elements()函数jsonb从Postgres中提取数据数组,它给出了错误:
不能从标量中提取元素
我认为这是因为NULL在返回调用中,添加了NULL检查条件但不起作用.任何帮助赞赏.
select id ,
CASE
WHEN report IS NULL OR
(report->'stats_by_date') IS NULL OR
(report->'stats_by_date'-> 'date') IS NULL then to_json(0)::jsonb
ELSE jsonb_array_elements(report -> 'stats_by_date' -> 'date')
END AS Date
from factor_reports_table
Run Code Online (Sandbox Code Playgroud)
截断的json数组看起来像:
"stats_by_date":{"date":[16632,16633,16634,...],"imps":[2418,896,1005 ......],...}
Kam*_*ski 15
重要说明:事情已从Postgres 10及更高版本更改,因此请根据您的数据库版本找到正确的解决方案.改变了什么?Postgres 10以后的CASE语句中不允许使用设置返回函数,这jsonb_array_elements是一个函数.
在您的数据中,必须有一些标量值而不是date键内的数组.
您可以识别特定键的类型jsonb_typeof(),然后将其包装在CASE语句中.
考虑下面的标量和数组示例作为输入集:
select
case when jsonb_typeof(jsonb_column->'stats_by_date'->'date') = 'array'
then jsonb_array_elements(jsonb_column->'stats_by_date'->'date')
else jsonb_column->'stats_by_date'->'date'
end as date
from (
select '{"stats_by_date": {"date": 123}}'::jsonb -- scalar (type: 'number')
union all
select '{"stats_by_date": {"date": [456]}}'::jsonb -- array (type: 'array')
) foo(jsonb_column);
Run Code Online (Sandbox Code Playgroud)
结果
date
------
123
456
Run Code Online (Sandbox Code Playgroud)
因此,您的查询需要像这样编写来处理这种情况:
select id,
case when jsonb_typeof(jsonb_column->'stats_by_date'->'date') = 'array'
then jsonb_array_elements(jsonb_column->'stats_by_date'->'date')
else jsonb_column->'stats_by_date'->'date'
end as date
from factor_reports_table
Run Code Online (Sandbox Code Playgroud)
由于不允许从Pg10设置返回函数,我们需要编写更多代码来实现相同的功能.设置返回函数意味着函数调用可以输出多行,并且不允许在CASE语句中使用.简单地说,Postgres希望我们为此编写显式代码.
逻辑保持与上面相同(参考10之前的pg版本),但我们将分两步而不是一步.
首先,我们需要找到两种类型的通用表示:数字和数组.我们可以从一个数字中创建一个数组,因此数组将是一个不错的选择.我们所做的是为每个案例构建一个数组(阅读评论):
case when jsonb_typeof(jsonb_column->'stats_by_date'->'date') = 'array' -- if array
then jsonb_column->'stats_by_date'->'date' -- leave it as it is
else jsonb_build_array(jsonb_column->'stats_by_date'->'date') -- if not array, build array
end as date
Run Code Online (Sandbox Code Playgroud)
第二步是将我们的数据类型转换包装在一个语句using WITH子句中,然后在FROM子句中使用函数调用从中进行选择,如下所示:
with json_arrays as (
select
case when jsonb_typeof(jsonb_column->'stats_by_date'->'date') = 'array'
then jsonb_column->'stats_by_date'->'date'
else jsonb_build_array(jsonb_column->'stats_by_date'->'date')
end as date
from (
select '{"stats_by_date": {"date": 123}}'::jsonb -- scalar (type: 'number')
union all
select '{"stats_by_date": {"date": [456]}}'::jsonb -- array (type: 'array')
) foo(jsonb_column)
)
select t.date
from
json_arrays j -- this is refering to our named WITH clause
, jsonb_array_elements(date) t(date) -- call function to get array elements
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11519 次 |
| 最近记录: |