如何计算嵌套在Postgresql JSON中的数字?

时间:2015-11-16 15:06:34

标签: json postgresql

我想对以Postgresql 9.4 JSON格式存储的数字进行一些操作。假设我有这张表:

CREATE TABLE t (id SERIAL, a JSON);

INSERT INTO t (a)
VALUES ('[[0.1, 2.0], [0.3, 4.0], [0.5, 6.0]]'),
       ('[[0.7, 8.0], [0.9, 10.0]]');

所以我可以用例如json_array_elements()

SELECT id, json_array_elements(a) AS sub1 FROM t;

id |   sub1
----------------
 1 | [0.1, 2.0]
 1 | [0.3, 4.0]
 1 | [0.5, 6.0]
 2 | [0.7, 8.0]
 2 | [0.9, 10.0]

请注意,元素的数量可能会有所不同。现在我想用子元素做一些计算,比如:

SELECT id,
       ((json_array_elements(a)->>0)::FLOAT) *
       ((json_array_elements(a)->>1)::FLOAT) as result
FROM t

但是我收到错误:ERROR: functions and operators can take at most one set argument。任何提示?

3 个答案:

答案 0 :(得分:3)

使用(隐式)LATERAL join代替:

SELECT id, (e->>0)::float * (e->>1)::float as result
FROM   t, json_array_elements(a) e

SELECT中的集合返回函数在PostgreSQL中非常特殊:

错误的确切原因是,您试图将两个集合相乘(这是不允许的)。 PostgreSQL可以计算<element> * <element>(将是单值),<set> * <element>(反之亦然;将是设置值),但不是<set> * <set>

答案 1 :(得分:1)

那是因为json_array_elements()返回 setof json。

您应该更好地按路径访问元素,如下所示:

SELECT
        id,
        (a#>>'{0,0}')::float * (a#>>'{0,1}')::float as result
    FROM processing.t;

关于错误是here

如果这不是一个选项,您可以使用子查询:

select
        id,
        (a->>0)::float * (a->>1)::float as result
    from (
        SELECT
                id,
                json_array_elements(a) as a
            FROM processing.t
    ) t;

在这种情况下,您可以按照自己的方式编写表达式。

答案 2 :(得分:0)

如果PostgreSQL的版本等于或大于当前问题的此代码,请不要引起错误。我用this进行了拨弄。

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<li>
  <a href="/analytics">
    <i class="fa fa-bar-chart analytics"></i> Analytics
    <span class="badge badge-success pull-right">1</span>
  </a>
</li>