SELECT列表中两次与jsonb_array_elements_text()不一致的结果

时间:2019-06-12 18:25:05

标签: sql arrays postgresql set-returning-functions

当数组中的元素数改变时,为什么下面的查询行为会改变?

以下代码段在同一查询上扩展了两个数组,并具有两种不同的行为:

  • 当两个数组具有相同数量的元素时,每行一行 元素被返回
  • 当两个数组的数目不同时 元素,其行为类似于CROSS JOIN

所有这些操作均在 Postgres 9.5.2 中执行:

CREATE TABLE test(a text, b jsonb, c jsonb);

INSERT INTO test VALUES
('A', '["b1","b2"]', '["c1","c2"]'),
('B', '["b1","b2"]', '["c1","c2","c3"]');

SELECT a, jsonb_array_elements_text(b) b, jsonb_array_elements_text(c) c
FROM test;

这是结果:

A  b1  c1
A  b2  c2
B  b1  c1
B  b2  c2
B  b1  c3
B  b2  c1
B  b1  c2
B  b2  c3

这是我期望的:

A  b1  c1
A  b1  c2
A  b2  c1
A  b2  c2
B  b1  c1
B  b2  c2
B  b1  c3
B  b2  c1
B  b1  c2
B  b2  c3

1 个答案:

答案 0 :(得分:1)

SELECT列表中组合多个返回集合的函数不在SQL标准中,在SQL标准中,所有返回集合的元素都进入FROM列表。您可以在Postgres中执行此操作,但是在版本10最终经过消毒之前,它曾经表现出令人惊讶的行为。

所有这些都不与数据类型jsonb或函数jsonb_array_elements_text()直接相关-除了它是一个返回集合的函数之外。

如果要可靠地使用笛卡尔积,而不取决于您的Postgres版本,请改用CROSS JOIN LATERAL(至少需要Postgres 9.3):

SELECT t.a, jb.b, jc.c
FROM   test t
     , jsonb_array_elements_text(t.b) jb(b)
     , jsonb_array_elements_text(t.c) jc(c)
ORDER  BY t.a, ???;  -- your desired order seems arbitrary beyond a

FROM列表(,)中的逗号基本上是CROSS JOIN LATERAL的简短语法。

请参阅:

您的实际问题的解释:

  

当数组中的元素数改变时,为什么下面的查询行为会改变?