fad*_*bee 33 sql postgresql casting jsonb postgresql-9.4
我正在尝试以下查询:
SELECT (json_data->'position'->'lat') + 1.0 AS lat FROM updates LIMIT 5;
Run Code Online (Sandbox Code Playgroud)
(+ 1.0只是强制转换为浮点数.我的实际查询要复杂得多,这个查询只是问题的一个测试用例.)
我收到错误:
ERROR: operator does not exist: jsonb + numeric
Run Code Online (Sandbox Code Playgroud)
如果我添加显式转换:
SELECT (json_data->'position'->'lat')::float + 1.0 AS lat FROM updates LIMIT 5;
Run Code Online (Sandbox Code Playgroud)
错误变成:
ERROR: operator does not exist: jsonb + double precesion
Run Code Online (Sandbox Code Playgroud)
我知道大多数jsonb值都不能转换成浮点数,但在这种情况下我知道lats都是JSON数.
是否有一个函数将jsonb值转换为浮点数(或为uncastable返回NULL)?
Igo*_*nko 84
有两种操作可以从中获取价值JSON.第一个->将返回JSON.第二个->>将返回文本.
详细信息:JSON函数和运算符
尝试
SELECT (json_data->'position'->>'lat')::float + 1.0 AS lat
FROM updates
LIMIT 5
Run Code Online (Sandbox Code Playgroud)
Pet*_*uss 12
现在我们可以直接从 JSONb 转换为 SQL 数据类型。我正在使用 PostgreSQL v12.3,它工作正常:
\nSELECT (j->\'i\')::int, (j->>\'i\')::int, (j->\'f\')::float, (j->>\'f\')::float\nFROM (SELECT \'{"i":123,"f":12.34}\'::jsonb) t(j); \nRun Code Online (Sandbox Code Playgroud)\n子问题:
\n从哪个版本可以?
\n它是语法糖还是真正的转换?
\n如果真正的“二进制JSONb\xe2\x86\x92二进制SQL”转换,微优化在哪里?
例如,什么会比“二进制 JSONb \xe2\x86\x92 字符串 \xe2\x86\x92 二进制 SQL”更快(?)?布尔\xe2\x86\x92布尔值,数字\xe2\x86\x92数字,数字\xe2\x86\x92int,数字\xe2\x86\x92bigint;数字\xe2\x86\x92float,数字\xe2\x86\x92double。
为什么不针对 NULL 进行优化?
奇怪的是,“NULL 到 SqlType”不起作用,“错误:无法将 jsonb null 转换为整数类型”。
如何检查?PostgreSQL何时优化循环查询?
\nEXPLAIN ANALYSE SELECT (j->\'i\')::int, (j->\'f\')::float -- bynary to bynary INT and FLOAT\n-- EXPLAIN ANALYSE SELECT (j->>\'i\')::int, (j->>\'f\')::float -- string to bynary INT and FLOAT\n\n-- EXPLAIN ANALYSE SELECT (j->\'i\')::numeric, (j->\'f\')::numeric -- bynary to bynary NUMERIC\n-- EXPLAIN ANALYSE SELECT (j->>\'i\')::numeric, (j->>\'f\')::numeric -- string to bynary NUMERIC\n\nFROM (\n SELECT ((\'{"i":\'||x||\',"f":\'||x||\'.34}\')::jsonb) as j FROM generate_series(1,599999) g(x)\n -- SELECT ((\'{"i":123,"f":12.34}\')::jsonb) as j FROM generate_series(1,599999) g(x)\n) t;\nRun Code Online (Sandbox Code Playgroud)\n即使是现在,2021 年版本 pg13 版本...不强制转换 NULL 是没有意义的:自然是强制转换NULL::int为整数,但 PostgreSQL 在自动强制转换中失败:
SELECT (j->\'i\')::int FROM (SELECT \'{"i":null}\'::jsonb) t(j); -- fail\nRun Code Online (Sandbox Code Playgroud)\n结果是“错误:无法将 jsonb null 转换为整数类型”。
\n根据文档,还有功能
jsonb_populate_record()
jsonb_populate_recordset()
Run Code Online (Sandbox Code Playgroud)
与他们的json双胞胎类比(自第9.3页开始)
json_populate_record()
json_populate_recordset()
Run Code Online (Sandbox Code Playgroud)
您需要预定义的行类型.使用现有表的行类型或使用CREATE TYPE.或者用临时表替换:
CREATE TEMP TABLE x(lat float);Run Code Online (Sandbox Code Playgroud)
可以是单列或长列列.
只有那些中填入,其中名字一个匹配关键的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;
Run Code Online (Sandbox Code Playgroud)
在这里使用隐含LATERAL JOIN.
同样,使用jsonb_populate_recordset()每个条目将数组分解为多行.
这在Postgres 9.3中的工作方式与此相同json.还有一个额外的好处,text就是数字数据不需要内部进/出内部jsonb.
添加说明,因为这是“JSONB 浮点转换”搜索的热门搜索 - 请注意,您需要将 JSON 转换括在方括号中,然后应用“::”转换。
如上所述,正确的方法是:
(json_data #>> '{field}')::float
Run Code Online (Sandbox Code Playgroud)
相反,如果您尝试这样做,它将失败:
json_data #>> '{field}'::float
Run Code Online (Sandbox Code Playgroud)
这是我在代码中犯的错误,我花了一段时间才看到它 - 一旦我注意到就很容易修复。
| 归档时间: |
|
| 查看次数: |
35339 次 |
| 最近记录: |