PostgreSQL n阶乘计算, 排列组合计算 - 如何计算可变参数中有没有重复参数
背景
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)