sql - 是否有一个函数可以让我输出 json 数组中元素的当前索引?

标签 sql json postgresql select postgresql-9.4

我有以下示例 Postgres SQL 查询。

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;

它输出下表。

+-----------+-----+
|   name    | id  |
+-----------+-----+
| Dingsda   | 100 |
| Dingsda   | 200 |
| Dingsbums | 101 |
| Dingsbums | 201 |
+-----------+-----+

现在我想要实现的是在末尾放置第三列,其中包含以 0 开头的 json 数组元素的索引,依此类推。结果应如下所示。

+-----------+-----+-------+
|   name    | id  | index |
+-----------+-----+-------+
| Dingsda   | 100 |     0 |
| Dingsda   | 200 |     1 |
| Dingsbums | 101 |     0 |
| Dingsbums | 201 |     1 |
| Dingsbums | 301 |     2 |
+-----------+-----+-------+

不幸的是,我还没有找到可以帮助我的功能。我尝试使用 row_number() OVER 进行试验,但当涉及 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;
+-----------+-----+-------+
|   name    | id  | index |
+-----------+-----+-------+
| Dingsbums | 101 |     1 |
| Dingsbums | 201 |     2 |
| Dingsbums | 301 |     3 |
| Dingsda   | 100 |     1 |
| Dingsda   | 400 |     2 |
| Dingsda   | 200 |     3 |
| Dingsda   | 300 |     4 |
+-----------+-----+-------+

最佳答案

切勿在 SELECT 子句中使用集合返回函数(例如 json_array_elements()),除非您确切地知道自己在做什么。这只会让你的事情变得更难。

您可以使用 WITH ORDINALITY表函数 (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");

您还可以使用 generate_series()使用 json_array_length(),但 WITH ORDINALITY 更简单。

关于sql - 是否有一个函数可以让我输出 json 数组中元素的当前索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42418170/

相关文章:

MySQL group_concat 与限制和连接

php - 如何从php中的android应用程序的post方法解码json数据?

ios - 使用我创建的 .json 数据库

c# - 将 JSON 数组值合并到单个 CSV 列中

sql - 将集合更新、插入或删除到表中

postgresql - Spring Boot postgres 无法确定合适的驱动程序类

sql - 使用 Postgresql 高效查询最新记录

sql - Rails 计数从 pluck 返回的值

sql - 是否可以在多个更新中使用 WITH 子句而不将其复制到每个更新中?

sql - PostgreSQL:合并两个表中的记录并计算平均值