从jsonb_array_elements或jsonb_to_recordset获取row_number

时间:2017-10-18 20:50:39

标签: json postgresql jsonb

我在jsonb数组上进行横向交叉连接,我希望得到数组元素的row_number(或它的等价物)。看看row_number文档我发现我需要做一个"命令"除了""之外的分区,但我并没有真正的排序标准 - 数组只有一个设定顺序,我需要将索引检索到数组中其余的数据。

客户端表格将包含这样的条目

{
  "id": "cj49q33oa000",
  "email": {
    "address": "",
    "after": "2016-06-28T12:28:58.016Z",
    "error": "Et corporis sed."
  },
  "name": "Arnold Schinner",
  "birthdate": "2016-07-29T05:09:33.693Z",
  "status": "paused",
  "sex": "f",
  "waist": [
    {
      "completed": "2017-06-23T10:37:37.500Z"
    },
    {
      "planned": "2017-06-23T10:37:37.500Z"
    },
    {
      "planned": "2017-06-23T10:37:37.500Z"
    },
    {
      "planned": "2017-06-23T10:37:37.500Z"
    }
  ]
}

我会运行像

这样的查询
SELECT client->>'id' AS id, waist.planned
FROM clients
CROSS JOIN LATERAL JSONB_TO_RECORDSET(client->'waist') AS waist(planned TIMESTAMP WITH TIME ZONE)
WHERE waist.planned IS NOT NULL

但我需要以某种方式获得waist.position_in_array

2 个答案:

答案 0 :(得分:1)

使用功能jsonb_array_elements(...) with ordinality.

SELECT client->>'id' AS id, (value->>'planned')::timestamptz as planned, ordinality
FROM clients
CROSS JOIN LATERAL jsonb_array_elements(client->'waist') with ordinality
WHERE value->>'planned' IS NOT NULL;

      id      |         planned          | ordinality 
--------------+--------------------------+------------
 cj49q33oa000 | 2017-06-23 12:37:37.5+02 |          1
 cj49q33oa000 | 2017-06-23 12:37:37.5+02 |          2
 cj49q33oa000 | 2017-06-23 12:37:37.5+02 |          3
 cj49q33oa000 | 2017-06-23 12:37:37.5+02 |          4
(4 rows)    

答案 1 :(得分:0)

您可以使用ROWS FROM语法将json_to_recordsetjsonb_to_recordsetWITH ORDINALITY组合在一起。

9.5年代的文档说

ROWS FROM(function_call [,...])[有序性] [[AS] table_alias [(column_alias [,...])]]

所以这可行(已在12上测试,但至少应在所有> = 9.5的版本上可行)

WITH my_json AS (
    SELECT '[{"id":1, "name":"somename", "bool":true},{"id":2, "name":null, "bool":false}]'::json jsn
)
SELECT jsn_with_ordinality.*
FROM my_json,
    ROWS FROM (json_to_recordset(jsn) AS (id int, name TEXT, bool boolean)) WITH ORDINALITY jsn_with_ordinality;

结果:

id|name    |bool |ordinality|
--|--------|-----|----------|
 1|somename|true |         1|
 2|        |false|         2|

但是,我确实想知道是否比添加row_number() over()...

更安全?