简短回答:不,在接受输出可能随机排序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
将在最终输出中配对,以便X1
rowN
的值将面对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 函数调用的子句将以通用方式提供此功能。