在 Postgres 11.7 中将 ORDINALITY 添加到扩展的 JSON 数组

Add ORDINALITY to expanded JSON array in Postgres 11.7

我正在使用两个 JSONB 数组,将它们解包,然后组合结果。我正在尝试将 WITH ORDINALITY 添加到 JSON 数组解包中。我一直想不出如何添加 WITH ORDINALITY。出于某种原因,我在 Postgres 11 的 JSON 工具的文档中找不到 WITH ORDINALITY

https://www.postgresql.org/docs/11/functions-json.html

我看过使用 jsonb_array_elements....WITH ORDINALITY 的示例,但无法使其正常工作。首先是一个基于Postgres数组的函数示例:

WITH
first AS (
SELECT * FROM
    UNNEST (ARRAY['Charles','Jane','George','Percy']) WITH ORDINALITY AS x(name_, index)
),

last AS (
SELECT * FROM
    UNNEST (ARRAY['Dickens','Austen','Eliot']) WITH ORDINALITY AS y(name_, index)
)

SELECT first.name_ AS first_name,
       last.name_  AS last_name

  FROM first
  JOIN last ON (last.index = first.index)

这给出了所需的输出:

first_name  last_name
Charles     Dickens
Jane        Austen
George      Eliot

我正在使用 ORDINALITY 索引来制作 JOIN,因为我正在合并两个列表以进行成对比较。我可以假设我的列表大小相同。

但是,我的输入将是一个 JSON 数组,而不是 Postgres 数组。我已经使用 jsonb_to_recordset 进行了解包,但还没有进行序数生成。这是一个正确执行解包部分的示例:

DROP FUNCTION IF EXISTS tools.try_ordinality (jsonb, jsonb);
CREATE OR REPLACE FUNCTION tools.try_ordinality (
     base_jsonb_in         jsonb,
     comparison_jsonb_in   jsonb)

RETURNS TABLE (
    base_text         citext,
    base_id           citext,
    comparison_text   citext,
    comparison_id     citext)

AS $BODY$

BEGIN

RETURN QUERY

WITH
base_expanded AS (

 select *
   from jsonb_to_recordset (
          base_jsonb_in) 
      AS base_unpacked (text citext, id citext)
 ),

comparison_expanded AS (

 select *
   from jsonb_to_recordset (
          comparison_jsonb_in)
      AS comparison_unpacked (text citext, id citext)
 ),

combined_lists AS (
select base_expanded.text       AS base_text,
       base_expanded.id         AS base_id,
       comparison_expanded.text AS comparison_text,
       comparison_expanded.id   AS comparison_id

  from base_expanded,
       comparison_expanded
)

select * 

   from combined_lists;

END
$BODY$
LANGUAGE plpgsql;
select *  from try_ordinality (
'[
    {"text":"Fuzzy Green Bunny","id":"1"},
    {"text":"Small Gray Turtle","id":"2"}
    ]',

'[
    {"text":"Red Large Special","id":"3"},
    {"text":"Blue Small","id":"4"},
    {"text":"Green Medium Special","id":"5"}
  ]'
);

但那是 CROSS JOIN

base_text    base_id    comparison_text    comparison_id
Fuzzy Green Bunny    1    Red Large Special      3
Fuzzy Green Bunny    1    Blue Small             4
Fuzzy Green Bunny    1    Green Medium Special   5
Small Gray Turtle    2    Red Large Special      3
Small Gray Turtle    2    Blue Small             4
Small Gray Turtle    2    Green Medium Special   5

我正在寻找只有两行的成对结果:

Fuzzy Green Bunny    1    Red Large Special    3
Small Gray Turtle    2    Blue Small           4

我试过切换到 jsonb_array_elements,如以下代码片段所示:

WITH
base_expanded AS (

 select *
   from jsonb_array_elements (
          base_jsonb_in) 
      AS base_unpacked (text citext, id citext)
 ),

我回来了

ERROR:  a column definition list is only allowed for functions returning "record"

是否有直接的方法来获取解压缩的 JSON 数组的序数?在 Postgres 数组上使用 UNNEST 非常容易。

感谢您的任何建议。

你做的完全一样。

with first as (
  select *
  from jsonb_array_elements('[
    {"text":"Fuzzy Green Bunny","id":"1"},
    {"text":"Small Gray Turtle","id":"2"}
    ]'::jsonb) with ordinality as f(element, idx)
), last as (
  select *
  from jsonb_array_elements('[
    {"text":"Red Large Special","id":"3"},
    {"text":"Blue Small","id":"4"},
    {"text":"Green Medium Special","id":"5"}
  ]'::jsonb) with ordinality as f(element, idx)
)
SELECT first.element ->> 'text' AS first_name,
       last.element ->> 'text' AS last_name
FROM first
  JOIN last ON last.idx = first.idx