PostgreSQL同长度数组列调用unnest表函数的非预期行为问题
我原本认为使用表函数时,会为当前行生成关联的新行,每个新行可包含多列,每列存储所引用表达式基于当前行求值得到的单个值。
文字表述可能较为冗长且不够清晰,可运行如下示例,查看结果行中数组元素的组合规则:
测试语句1:
select id, unnest(numbers), unnest(letters) from ( values (1, ARRAY[1,2], ARRAY['a','b', 'c']), (2, ARRAY[3,4], ARRAY['d','e', 'f']) ) as aTable(id,numbers,letters)
运行该语句时,数据库会逐行将数组视为集合,生成类笛卡尔积的组合结果。
测试语句2:
select id, unnest(numbers), unnest(letters) from ( values (1, ARRAY[1,2], ARRAY['a','b']), (2, ARRAY[3,4], ARRAY['d','e']) ) as aTable(id,numbers,letters)
该语句中两个入参数组长度完全一致,我本预期会得到和上一个示例相同的笛卡尔积结果,但实际输出采用了不同的组合规则。经同事提醒,该现象可能与参与运算的数组长度相同有关。我查阅了PostgreSQL 14官方文档中表表达式章节的表函数相关内容,未找到对应规则说明,希望了解该现象的底层逻辑,以及如何在数组等长场景下强制生成笛卡尔积结果。
更新(收到Laurenz的答复后补充)
若要实现数组元素的全量笛卡尔积组合,可将表函数移入FROM子句,通过lateral join实现,参考语句如下:
select id,number,letter from ( values (1, ARRAY[1,2], ARRAY['a','b']), (2, ARRAY[3,4], ARRAY['d','e']) ) as aTable(id,numbers,letters) cross join lateral unnest(numbers) as number cross join lateral unnest(letters) as letter
内容的提问来源于stack exchange,提问作者Victor
相关产品推荐
相关产品推荐

