简短回答:不,在接受输出可能随机排序idx的前提时,不会匹配数组位置。unnest()
Demo:由于当前的实现unnest实际上是按照元素的顺序输出行,所以我建议在它上面加一层来模拟随机顺序:
CREATE FUNCTION unnest_random(anyarray) RETURNS setof anyelement
language sql as
$$ select unnest($1) order by random() $$;
然后检查您的查询的一些执行,unnest替换为unnest_random:
SELECT
unnest_random(ARRAY[5,3,9]) as id,
unnest_random(ARRAY(select generate_series(1, array_length(ARRAY[5,3,9], 1)))) as idx
ORDER BY idx ASC
输出示例:
编号 | 编号
-+-----
3 | 1
9 | 2
5 | 3
id=3关联idx=1但3在数组中的第二个位置。都是错的。
查询有什么问题:它假设第一个unnest将使用与第二个相同的排列unnest(数学意义上的排列:数组中的顺序和行的顺序之间的关系)来打乱元素。但是这个假设与订单输出一unnest开始就不可预测的前提相矛盾。
关于这个问题:
是否保证 2 个 unnest() 调用(具有相同的长度)将并行展开
in select unnest(...) X1, unnest(...) X2, withX1和X2是 typeSETOF something并且具有相同的行数,X1并且X2将在最终输出中配对,以便X1rowN的值将面对X2同一 row的值N。(它是一种列的 UNION,而不是笛卡尔积)。
但我不会将这种配对描述为并行展开,所以我不确定这就是你的意思。
无论如何,这种配对对解决问题没有帮助,因为它发生在未嵌套调用丢失数组位置之后。
另一种选择:在pgsql-sql 邮件列表中的这个线程中,建议使用此功能:
CREATE OR REPLACE FUNCTION unnest_with_ordinality(anyarray, OUT value
anyelement, OUT ordinality integer)
RETURNS SETOF record AS
$$
SELECT $1[i], i FROM
generate_series(array_lower($1,1),
array_upper($1,1)) i;
$$
LANGUAGE sql IMMUTABLE;
基于此,我们可以按第二个输出列排序:
select * from unnest_with_ordinality(array[5,3,9]) order by 2;
价值 | 序数
--------+------------
5 | 1
3 | 2
9 | 3
对于 postgres 9.4 及更高版本:WITH ORDINALITY可以遵循 SET RETURNING 函数调用的子句将以通用方式提供此功能。