jsonb cross join 在 Postgres 中没有 return N*M 行

jsonb cross join did not return N*M rows in Postgres

CREATE TABLE mytable (
                         id int,
                         user_id text,
                         changes jsonb,
                         exercise_entry_id int
);

INSERT INTO mytable VALUES
                        (1, 'foo', '["a","b"]', 3),
                        (2, 'foo', '["c","d"]', 3);

交叉连接查询:

SELECT
        mytable.*,
        elems
    FROM
        mytable  cross  join
        jsonb_array_elements(changes) as elems
    order by mytable.id;

但是这个查询 returns 只有 4 行,如附图所示。交叉连接应该 return 8 行。现在只有 return 4 行,我错过了什么?

这是横向交叉连接。我在手册上找到它。

When a FROM item contains LATERAL cross-references, evaluation proceeds as follows: for each row of the FROM item providing the cross-referenced column(s), or set of rows of multiple FROM items providing the columns, the LATERAL item is evaluated using that row or row set's values of the columns. The resulting row(s) are joined as usual with the rows they were computed from. This is repeated for each row or set of rows from the column source table(s).

此查询 returns 8 行是 mytable 行 (2) 和所有数组的所有元素的笛卡尔积 changes (4):

select
    mytable.*,
    elems
from mytable  
cross join (
    select jsonb_array_elements(changes) as elems
    from mytable
    ) s
order by id;

与子查询的横向连接比较(returns 4行):

select
    mytable.*,
    elems
from mytable  
cross join lateral (
    select jsonb_array_elements(changes) as elems
    ) s
order by id;

子查询可以被一个简单的函数调用所取代,在这种情况下 lateral 这个词是可选的。

查找详细说明in the documentation.

如果您在 FROM 子句中使用 table 函数,则它隐含地是一个 LATERAL 连接,因此它会将每一行与该行的函数结果连接起来。

参见the documentation

Table functions appearing in FROM can also be preceded by the key word LATERAL, but for functions the key word is optional; the function's arguments can contain references to columns provided by preceding FROM items in any case.

也许这可以帮助实现您的需求

with temp as
(
 select jsonb_array_elements( changes)    from mytable
)
select * from mytable m1
cross join temp

结果: