我正在尝试以下查询:
SELECT (json_data->'position'->'lat') + 1.0 AS lat FROM updates LIMIT 5;
(+1.0就是强制转换为浮点数。我的实际查询要复杂得多,这个查询只是问题的一个测试用例。)
我收到错误:
ERROR: operator does not exist: jsonb + numeric
如果我添加显式转换:
SELECT (json_data->'position'->'lat')::float + 1.0 AS lat FROM updates LIMIT 5;
错误变为:
ERROR: operator does not exist: jsonb + double precesion
据我所知,大多数jsonb值都不能转换为浮点值,但在这种情况下,我知道这些值都是JSON数。
是否有一个函数将jsonb值转换为浮点数(或者为uncastable返回NULL)?
答案 0 :(得分:73)
有两项操作可以从JSON
获取价值。第一个->
将返回JSON
。第二个->>
将返回文本。
详细信息:JSON Functions and Operators
尝试
SELECT (json_data->'position'->>'lat')::float + 1.0 AS lat
FROM updates
LIMIT 5
答案 1 :(得分:6)
Per documentation,还有函数
jsonb_populate_record()
jsonb_populate_recordset()
模拟他们的json双胞胎(自第9.3页开始)
json_populate_record()
json_populate_recordset()
您需要预定义的行类型。使用现有表的行类型或使用CREATE TYPE
定义一个。或者用临时临时表替换:
CREATE TEMP TABLE x(lat float);
可以是单列或长列列。
仅填充这些列,其中名称与json
对象中的键匹配。 值会强制转换为类型列,并且必须兼容或引发异常。其他键被忽略。
SELECT lat + 1 -- no need for 1.0, this is float already
FROM updates u
, jsonb_populate_record(NULL::x, u.json_data->'position')
LIMIT 5;
在这里使用implicit LATERAL JOIN
。
同样,使用jsonb_populate_recordset()
将数组分解为每个条目的多行。
这与使用json
的Postgres 9.3中的工作方式相同。 text
中的数字数据不需要内部投放到jsonb
内部的额外好处。
答案 2 :(得分:4)
AFAIK在Postgres中没有json->浮动播放,所以你可以尝试一个明确的(json_data->'position'->'lat')::text::float
强制转换
答案 3 :(得分:3)
添加一个说明,因为这是“ JSONB浮点转换”搜索的热门内容-请注意,您需要将JSON转换包装在方括号中,然后然后应用'::'
如上所述,正确的方法是:
(json_data #>> '{field}')::float
如果您尝试这样做,它将失败:
json_data #>> '{field}'::float
这是我在代码中犯的错误,花了我一段时间才能看到它-一旦发现,就可以轻松解决。
答案 4 :(得分:1)
您必须将json值转换为text,然后再浮动。
试试这个:
config.Routes.MapHttpRoute(
name: "GetAllRoute",
routeTemplate: "api/{controller}.{ext}"/*,
defaults: new { action = "Get" }*/ // this was causing the issue
);
答案 5 :(得分:0)
创建视图时,我使用了CAST:
create view mydb.myview as
select id,
config->>'version' as version,
config->>'state' as state,
config->>'name' as name,
config->>'internal-name' as internal_name,
config->>'namespace' as namespace,
create_date,
update_date,
CAST(config ->> 'version' as double precision) as version_number
from mydb.mytbl;
答案 6 :(得分:0)
如今,我们可以直接从JSONb转换为SQL数据类型。我使用的是PostgreSQL v12.3 ,在这里运行良好:
SELECT (j->'i')::int, (j->>'i')::int, (j->'f')::float, (j->>'f')::float
FROM (SELECT '{"i":123,"f":12.34}'::jsonb) t(j);
子问题:
可以从哪个版本开始?
它是语法糖还是real conversion?
如果是真正的“二进制JSONb→二进制SQL”转换,则在哪里进行微优化?
例如,请问“二进制JSONb→字符串”更快吗? →二进制SQL”?布尔值→布尔值,数字→数字,数字→int,数字→bigint;数字→浮动,数字→双。
为什么不针对NULL优化?
奇怪的是,“将NULL转换为SqlType”无效,“错误:无法将jsonb null强制转换为整数”。
如何检查? PostgreSQL何时优化循环查询?
EXPLAIN ANALYSE SELECT (j->'i')::int, (j->'f')::float -- bynary to bynary INT and FLOAT
-- EXPLAIN ANALYSE SELECT (j->>'i')::int, (j->>'f')::float -- string to bynary INT and FLOAT
-- EXPLAIN ANALYSE SELECT (j->'i')::numeric, (j->'f')::numeric -- bynary to bynary NUMERIC
-- EXPLAIN ANALYSE SELECT (j->>'i')::numeric, (j->>'f')::numeric -- string to bynary NUMERIC
FROM (
SELECT (('{"i":'||x||',"f":'||x||'.34}')::jsonb) as j FROM generate_series(1,599999) g(x)
-- SELECT (('{"i":123,"f":12.34}')::jsonb) as j FROM generate_series(1,599999) g(x)
) t;