Sql 是否有一个函数允许我输出json数组中元素的当前索引?

Sql 是否有一个函数允许我输出json数组中元素的当前索引?,sql,json,postgresql,select,postgresql-9.4,Sql,Json,Postgresql,Select,Postgresql 9.4,我有以下示例PostgresSQL查询 SELECT name, json_array_elements(myjson)->>'id' id FROM (SELECT 'Dingsda'::text AS name, json_build_array('{"id" : 100}'::json, '{"id" : 200}'::json) myjson UNION ALL SELECT 'Dingsbums'::text AS name, json_build_array('{"

我有以下示例PostgresSQL查询

SELECT name, json_array_elements(myjson)->>'id' id FROM
(SELECT 'Dingsda'::text AS name, json_build_array('{"id" : 100}'::json, '{"id" : 200}'::json) myjson
  UNION ALL
 SELECT 'Dingsbums'::text AS name, json_build_array('{"id" : 101}'::json, '{"id" : 201}'::json, '{"id" : 301}'::json) myjson
) t;
它输出下表

+-----------+-----+
|姓名| id|
+-----------+-----+
|丁斯达| 100|
|丁斯达| 200|
|丁斯本斯| 101|
|丁斯本斯| 201|
+-----------+-----+
现在,我试图实现的是在末尾添加第三列,其中包含json数组元素的索引,从0开始,以此类推。结果应该如下所示

+-----------+-----+-------+
|名称| id |索引|
+-----------+-----+-------+
|丁斯达| 100 | 0|
|丁斯达| 200 | 1|
|丁斯本斯| 101 | 0|
|丁斯本斯| 201 | 1|
|丁斯本斯| 301 | 2|
+-----------+-----+-------+
不幸的是,我还没有找到一个可以帮助我的函数。我尝试在上使用
row_number(),但当涉及到
json
类型化列时,它似乎会返回奇怪的结果

是否有任何功能可以支持这个相当简单的需求

编辑 Mureinik的回答很有帮助,但是我希望能够保留json中元素的原始序列。在本例中,序列丢失。我认为这是不确定的

SELECT name, id, ROW_NUMBER() OVER (PARTITION BY name ORDER BY 1)
FROM (SELECT name, JSON_ARRAY_ELEMENTS(myjson)->>'id' id 
      FROM   (SELECT 'Dingsda'::text AS name, JSON_BUILD_ARRAY('{"id" : 100}'::json, '{"id" : 200}'::json, '{"id" : 300}'::json, '{"id" : 400}'::json) myjson
          UNION ALL
          SELECT 'Dingsbums'::text AS name, JSON_BUILD_ARRAY('{"id" : 101}'::json, '{"id" : 201}'::json, '{"id" : 301}'::json) myjson
         ) t
      ) s;
+-----------+-----+-------+
|名称| id |索引|
+-----------+-----+-------+
|丁斯本斯| 101 | 1|
|丁斯本斯| 201 | 2|
|丁斯本斯| 301 | 3|
|丁斯达| 100 | 1|
|丁斯达| 400 | 2|
|丁斯达| 200 | 3|
|丁斯达| 300 | 4|
+-----------+-----+-------+

使用
行数
似乎是正确的方法。您只需将此查询与另一个查询打包即可生成行的编号:

SELECT name, id, ROW_NUMBER() OVER (PARTITION BY name ORDER BY 1)
FROM (SELECT name, JSON_ARRAY_ELEMENTS(myjson)->>'id' id 
      FROM   (SELECT 'Dingsda'::text AS name, JSON_BUILD_ARRAY('{"id" : 100}'::json, '{"id" : 200}'::json) myjson
              UNION ALL
              SELECT 'Dingsbums'::text AS name, JSON_BUILD_ARRAY('{"id" : 101}'::json, '{"id" : 201}'::json, '{"id" : 301}'::json) myjson
             ) t
      ) s;

使用
行数
似乎是正确的方法。您只需将此查询与另一个查询打包即可生成行的编号:

SELECT name, id, ROW_NUMBER() OVER (PARTITION BY name ORDER BY 1)
FROM (SELECT name, JSON_ARRAY_ELEMENTS(myjson)->>'id' id 
      FROM   (SELECT 'Dingsda'::text AS name, JSON_BUILD_ARRAY('{"id" : 100}'::json, '{"id" : 200}'::json) myjson
              UNION ALL
              SELECT 'Dingsbums'::text AS name, JSON_BUILD_ARRAY('{"id" : 101}'::json, '{"id" : 201}'::json, '{"id" : 301}'::json) myjson
             ) t
      ) s;

切勿在
SELECT
子句中使用设置返回函数(如
json\u array\u elements()
),除非您确切知道自己在做什么。这只会让你更难受

您可以使用table functions(9.4+)的子句,它正是为了解决您的问题:

SELECT name, elem->>'id' id, "index"
FROM (SELECT 'Dingsda'::text AS name, json_build_array('{"id" : 100}'::json, '{"id" : 200}'::json) myjson
        UNION ALL
      SELECT 'Dingsbums'::text AS name, json_build_array('{"id" : 101}'::json, '{"id" : 201}'::json, '{"id" : 301}'::json) myjson) t,
     json_array_elements(t.myjson) WITH ORDINALITY e(elem, "index");

您也可以与
json_array_length()
一起使用,但将
与ORDINALITY
一起使用要简单得多。

除非您确切知道自己在做什么,否则不要在
SELECT子句中使用设置返回函数(例如
json_array_elements()
)。这只会让你更难受

您可以使用table functions(9.4+)的子句,它正是为了解决您的问题:

SELECT name, elem->>'id' id, "index"
FROM (SELECT 'Dingsda'::text AS name, json_build_array('{"id" : 100}'::json, '{"id" : 200}'::json) myjson
        UNION ALL
      SELECT 'Dingsbums'::text AS name, json_build_array('{"id" : 101}'::json, '{"id" : 201}'::json, '{"id" : 301}'::json) myjson) t,
     json_array_elements(t.myjson) WITH ORDINALITY e(elem, "index");

您也可以与
json_array_length()
一起使用,但与序数一起使用
更简单。

您可以使用横向连接(无论如何推荐)和与序数一起使用

SELECT name, x.element ->> 'id' as id, x.idx
FROM (
  SELECT 'Dingsda'::text AS name, json_build_array('{"id" : 100}'::json, '{"id" : 200}'::json) myjson
  UNION ALL
  SELECT 'Dingsbums'::text AS name, json_build_array('{"id" : 101}'::json, '{"id" : 201}'::json, '{"id" : 301}'::json) myjson
) t
  cross join lateral json_array_elements(myjson) with ordinality as x(element, idx)

您可以使用横向连接(无论如何推荐)和带有顺序性的

SELECT name, x.element ->> 'id' as id, x.idx
FROM (
  SELECT 'Dingsda'::text AS name, json_build_array('{"id" : 100}'::json, '{"id" : 200}'::json) myjson
  UNION ALL
  SELECT 'Dingsbums'::text AS name, json_build_array('{"id" : 101}'::json, '{"id" : 201}'::json, '{"id" : 301}'::json) myjson
) t
  cross join lateral json_array_elements(myjson) with ordinality as x(element, idx)

您好,这很有帮助,但在某些情况下,序列在此丢失。请看我的编辑。嗨,这很有帮助,但在某些情况下,序列在这里丢失。请看我的编辑。谢谢,我没有意识到这一点。关键字
均不具有顺序性
。非常有帮助!它还保留了数组元素的顺序。谢谢,我没有意识到这一点。关键字
均不具有顺序性
。非常有帮助!它还保留了数组元素的顺序。