Postgresql 如何在Postgres中转换/解析JSON striing为number/float?

Postgresql 如何在Postgres中转换/解析JSON striing为number/float?,postgresql,Postgresql,我的Postgres DB中有一个JSONB列。在某些情况下,它包含编码为字符串*的数字,例如:123或3.232或2.32e14。引号是存储的JSONB值的一部分,它是123而不是123 我想总结这些值,因此需要一种方法将它们视为浮点。我无法在PSQL中找到任何方法来实现这一点 select column::float失败,因为它们是JSON字符串,而不是DB文本类型。column::text::float也不起作用 选择to_numbercolumn::text,“999.999”不起作用,

我的Postgres DB中有一个JSONB列。在某些情况下,它包含编码为字符串*的数字,例如:123或3.232或2.32e14。引号是存储的JSONB值的一部分,它是123而不是123

我想总结这些值,因此需要一种方法将它们视为浮点。我无法在PSQL中找到任何方法来实现这一点

select column::float失败,因为它们是JSON字符串,而不是DB文本类型。column::text::float也不起作用

选择to_numbercolumn::text,“999.999”不起作用,因为to_number需要固定格式的数字,而且我找不到解析标准格式浮点数的方法

如何将JSONB字符串编码值转换为数字值进行计算


*背景:它们被存储为字符串,因为存储需要精确,并且在往返浮点的过程中无法保存。对于计算,可以将精度降低到浮动。它们可以在转换为高级十进制格式的往返过程中幸存下来,但Python库SQLAlchemy和JSON的一个局限性使其无法工作。即使我们在这里找到了解决方案,我仍然需要迁移现有数据,因此问题依然存在。

假设您使用的是postgresql 12+,您可以使用jsonpath方法来实现这一点:

WITH d(json) AS (
    VALUES ('"123"'::jsonb)
         , ('"3.232"')
         , ('"2.32e14"')
)
SELECT json, JSONB_TYPEOF(json), jsonb_path_query(json, '$.double()')
FROM d;
json jsonb_型 jsonb_路径_查询 123 一串 123 3.232 一串 3.232 2.32e14 一串 232000000000000
假设您使用的是postgresql 12+,您可以使用jsonpath方法来实现以下目的:

WITH d(json) AS (
    VALUES ('"123"'::jsonb)
         , ('"3.232"')
         , ('"2.32e14"')
)
SELECT json, JSONB_TYPEOF(json), jsonb_path_query(json, '$.double()')
FROM d;
json jsonb_型 jsonb_路径_查询 123 一串 123 3.232 一串 3.232 2.32e14 一串 232000000000000
此语法将类型转换为未转换的JSON值,然后强制转换为浮点:

值>>“{}”::浮点

例如,在总和中:

WITH d(json) AS (
    VALUES ('"123"'::jsonb)
         , ('"3.232"')
         , ('"2.32e14"')
)
SELECT SUM((json#>>'{}')::float)
FROM d;

这与@Marth给出的结果相同。我不确定哪种方法更正确、更有效或更可取。

此语法将类型转换为未转换的JSON值,然后强制转换为浮点:

值>>“{}”::浮点

例如,在总和中:

WITH d(json) AS (
    VALUES ('"123"'::jsonb)
         , ('"3.232"')
         , ('"2.32e14"')
)
SELECT SUM((json#>>'{}')::float)
FROM d;

这与@Marth给出的结果相同。我不确定哪种方法更正确、更有效或更受欢迎。

我不确定返回的是哪种类型,但结果似乎不适用于sum等计算。也就是说,选择sumjsonb_path_queryjson,'$。double不起作用。聚合函数调用不能包含集合返回函数调用。因此,我假定path函数是一个聚合函数,而不是一个值。@edA-qamort-ora-y:没错,jsonb_path_查询返回一个集合,因此在大多数情况下并不打算直接在SELECT子句中使用。我主要用它来显示$.double jsonpath可以工作。我首先添加了一个使用jsonb_path_query_的示例,它在这里工作得更好,因为它只返回一个结果。我尝试了::float cast,但函数的第一个变体是让它工作的技巧。我也找到了另一个解决方案,请参见我的答案。你知道哪种方法更有意义吗?我不确定返回的是哪种类型,但结果似乎在sum之类的计算中不可用。也就是说,选择sumjsonb_path_queryjson,'$。double不起作用。聚合函数调用不能包含集合返回函数调用。因此,我假定path函数是一个聚合函数,而不是一个值。@edA-qamort-ora-y:没错,jsonb_path_查询返回一个集合,因此在大多数情况下并不打算直接在SELECT子句中使用。我主要用它来显示$.double jsonpath可以工作。我首先添加了一个使用jsonb_path_query_的示例,它在这里工作得更好,因为它只返回一个结果。我尝试了::float cast,但函数的第一个变体是让它工作的技巧。我也找到了另一个解决方案,请参见我的答案。你知道哪种方法更有意义吗?我不会猜到当前路径上的值,因为你可以将查询写为json>>数组[]::text[]使用数组,要查找的路径将提取文本值本身并使其可转换,但这是有意义的。我在回答中看到的主要区别是,非数值的错误是泛型转换错误,例如,类型double precision vs jsonpath item method的输入语法无效。double只能应用于字符串或数值。我不能说哪一个更快,尽管我猜是你的。无论如何,有一个postgresql解决方案很好,我不会猜到当前路径上的值,因为您可以将查询写为json>>数组[]::text[]使用数组,要查找的路径将提取文本值本身并使其可转换,但这是有意义的。我在回答中看到的主要区别是,非数值的错误是泛型转换错误,例如,类型double precision vs jsonpath item method的输入语法无效。double只能应用于字符串或数值。我不能说哪一个更快,尽管我猜是你的。总之,有个解决方案很好 n用于postgresql