PostgreSQL 如何计算可变参数中有没有重复参数。
有一个计算排列组合的算法需求,需要知道参数中是否有重复值。目的是过滤掉重复值。
实现方法很简单,需要创建支持可变参数的函数,如下:
postgres=# CREATE or replace FUNCTION has_dupli_val(VARIADIC arr int[]) RETURNS boolean AS
$$
select count(distinct val)<>count(*) dist_val from unnest($1) t(val) where val is not null;
$$
language sql strict;
CREATE FUNCTION
postgres=# select has_dupli_val(1,2,null,1);
has_dupli_val
---------------
t
(1 row)
postgres=# select has_dupli_val(1,2,null,3);
has_dupli_val
---------------
f
(1 row)
postgres=# select has_dupli_val(1,2,null,null);
has_dupli_val
---------------
f
(1 row)
postgres=# select has_dupli_val(null,null);
has_dupli_val
---------------
f
(1 row)
还蛮简单的,用到了聚合判断,可变参数使用variadic 标记的数组来定义。
这个函数可以用来生成排列组合。
例子:
postgres=# create table t(id int);
CREATE TABLE
postgres=# insert into t select generate_series(1,5);;
INSERT 0 5
对1,2,3,4,5这5个值进行排列组合,得出组合结果。
排列组合的可能性有5的阶乘种。即120。
postgres=# select 5!;
?column?
----------
120
(1 row)
得到1,2,3,4,5的排列组合的方法:
postgres=# select t1.id,t2.id,t3.id,t4.id,t5.id from t t1,t t2,t t3,t t4,t t5 where not has_dupli_val(t1.id,t2.id,t3.id,t4.id,t5.id);
id | id | id | id | id
----+----+----+----+----
1 | 2 | 3 | 4 | 5
1 | 2 | 3 | 5 | 4
1 | 2 | 4 | 3 | 5
1 | 2 | 4 | 5 | 3
1 | 2 | 5 | 3 | 4
1 | 2 | 5 | 4 | 3
1 | 3 | 2 | 4 | 5
1 | 3 | 2 | 5 | 4
1 | 3 | 4 | 2 | 5
1 | 3 | 4 | 5 | 2
1 | 3 | 5 | 2 | 4
1 | 3 | 5 | 4 | 2
1 | 4 | 2 | 3 | 5
1 | 4 | 2 | 5 | 3
1 | 4 | 3 | 2 | 5
1 | 4 | 3 | 5 | 2
1 | 4 | 5 | 2 | 3
1 | 4 | 5 | 3 | 2
1 | 5 | 2 | 3 | 4
1 | 5 | 2 | 4 | 3
1 | 5 | 3 | 2 | 4
1 | 5 | 3 | 4 | 2
1 | 5 | 4 | 2 | 3
1 | 5 | 4 | 3 | 2
2 | 1 | 3 | 4 | 5
2 | 1 | 3 | 5 | 4
2 | 1 | 4 | 3 | 5
2 | 1 | 4 | 5 | 3
2 | 1 | 5 | 3 | 4
2 | 1 | 5 | 4 | 3
2 | 3 | 1 | 4 | 5
2 | 3 | 1 | 5 | 4
2 | 3 | 4 | 1 | 5
2 | 3 | 4 | 5 | 1
2 | 3 | 5 | 1 | 4
2 | 3 | 5 | 4 | 1
2 | 4 | 1 | 3 | 5
2 | 4 | 1 | 5 | 3
2 | 4 | 3 | 1 | 5
2 | 4 | 3 | 5 | 1
2 | 4 | 5 | 1 | 3
2 | 4 | 5 | 3 | 1
2 | 5 | 1 | 3 | 4
2 | 5 | 1 | 4 | 3
2 | 5 | 3 | 1 | 4
2 | 5 | 3 | 4 | 1
2 | 5 | 4 | 1 | 3
2 | 5 | 4 | 3 | 1
3 | 1 | 2 | 4 | 5
3 | 1 | 2 | 5 | 4
3 | 1 | 4 | 2 | 5
3 | 1 | 4 | 5 | 2
3 | 1 | 5 | 2 | 4
3 | 1 | 5 | 4 | 2
3 | 2 | 1 | 4 | 5
3 | 2 | 1 | 5 | 4
3 | 2 | 4 | 1 | 5
3 | 2 | 4 | 5 | 1
3 | 2 | 5 | 1 | 4
3 | 2 | 5 | 4 | 1
3 | 4 | 1 | 2 | 5
3 | 4 | 1 | 5 | 2
3 | 4 | 2 | 1 | 5
3 | 4 | 2 | 5 | 1
3 | 4 | 5 | 1 | 2
3 | 4 | 5 | 2 | 1
3 | 5 | 1 | 2 | 4
3 | 5 | 1 | 4 | 2
3 | 5 | 2 | 1 | 4
3 | 5 | 2 | 4 | 1
3 | 5 | 4 | 1 | 2
3 | 5 | 4 | 2 | 1
4 | 1 | 2 | 3 | 5
4 | 1 | 2 | 5 | 3
4 | 1 | 3 | 2 | 5
4 | 1 | 3 | 5 | 2
4 | 1 | 5 | 2 | 3
4 | 1 | 5 | 3 | 2
4 | 2 | 1 | 3 | 5
4 | 2 | 1 | 5 | 3
4 | 2 | 3 | 1 | 5
4 | 2 | 3 | 5 | 1
4 | 2 | 5 | 1 | 3
4 | 2 | 5 | 3 | 1
4 | 3 | 1 | 2 | 5
4 | 3 | 1 | 5 | 2
4 | 3 | 2 | 1 | 5
4 | 3 | 2 | 5 | 1
4 | 3 | 5 | 1 | 2
4 | 3 | 5 | 2 | 1
4 | 5 | 1 | 2 | 3
4 | 5 | 1 | 3 | 2
4 | 5 | 2 | 1 | 3
4 | 5 | 2 | 3 | 1
4 | 5 | 3 | 1 | 2
4 | 5 | 3 | 2 | 1
5 | 1 | 2 | 3 | 4
5 | 1 | 2 | 4 | 3
5 | 1 | 3 | 2 | 4
5 | 1 | 3 | 4 | 2
5 | 1 | 4 | 2 | 3
5 | 1 | 4 | 3 | 2
5 | 2 | 1 | 3 | 4
5 | 2 | 1 | 4 | 3
5 | 2 | 3 | 1 | 4
5 | 2 | 3 | 4 | 1
5 | 2 | 4 | 1 | 3
5 | 2 | 4 | 3 | 1
5 | 3 | 1 | 2 | 4
5 | 3 | 1 | 4 | 2
5 | 3 | 2 | 1 | 4
5 | 3 | 2 | 4 | 1
5 | 3 | 4 | 1 | 2
5 | 3 | 4 | 2 | 1
5 | 4 | 1 | 2 | 3
5 | 4 | 1 | 3 | 2
5 | 4 | 2 | 1 | 3
5 | 4 | 2 | 3 | 1
5 | 4 | 3 | 1 | 2
5 | 4 | 3 | 2 | 1
(120 rows)