PostgreSQL n阶乘计算, 排列组合计算 - 如何计算可变参数中有没有重复参数

6 minute read

背景

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)  

Flag Counter

digoal’s 大量PostgreSQL文章入口