SQL 和唯一的 n 列组合

Posted

技术标签:

【中文标题】SQL 和唯一的 n 列组合【英文标题】:SQL and unique n-column combinations 【发布时间】:2011-08-20 21:56:50 【问题描述】:

Oracle 上是否有一种简单的方法来查询 n 个字段的唯一组合。我有非常简单的两场解决方案:

CREATE TABLE combinations AS
SELECT 1 AS n 
  FROM DUAL
UNION ALL
SELECT 2
  FROM DUAL;

查询唯一组合:

SELECT LEAST(x.a, x.b), 
       GREATEST(x.a,x.b) 
  FROM (SELECT c1.n a, 
               c2.n b 
          FROM combinations c1
    CROSS JOIN combinations c2
         WHERE c1.n <> c2.n) x
GROUP BY LEAST(x.a, x.b), GREATEST(x.a,x.b);

从此查询中,1,2 和 2,1 被认为是相同的。不幸的是,它不适用于 3 字段结构(例如 1,2,3 必须被视为与 3,1,2 相同,因为值的顺序无关紧要)。 Oracle 分析函数是否为这个问题提供了适当的解决方案?您能否推荐一些特定的 Oracle 分析功能?

【问题讨论】:

您不只需要使用&lt; 而不是&lt;&gt; 加入吗? 【参考方案1】:

您对 2 列的查询可以这样重写:

SELECT
  c1.n,
  c2.n
FROM combinations c1
  INNER JOIN combinations c2 ON c1.n < c2.n

对于 3 列,您需要添加一些内容(以粗体突出显示):

SELECT
  c1.n,
  c2.n,
  c3.n
FROM combinations c1
  INNER JOIN combinations c2 ON c1.n < c2.n
  INNER JOIN combinations c3 ON c2.n < c3.n

我相信您现在可以很容易地猜出如何将其缩放到更多列。

【讨论】:

【参考方案2】:

您的解决方案在于使用pipelined table function 返回您的组合。

您的函数可以存在于它自己的包中(带有包状态),它按照您希望的顺序返回您需要的数据。状态将是一组由要返回的列数确定的变量,初始化为初始起始值(A=1、B=A+1、C=B+1、D=C+1 等)。那你只是

PIPE ROW(a,b,c,d);
-- increment D
-- if D overflow limit, increment C and re-init D to C+1
-- if C overflow limit-1, increment B and re-init C to B+1
-- if B overflow limit-2, increment A and re-init B to A+1
-- if A overflow limit-3, the end

这个输出,对于 N = 6

 1,2,3,4
 1,2,3,5
 1,2,3,6
 1,2,4,5
 1,2,4,6
 1,3,4,5
 1,3,4,6
 2,3,4,5
 2,3,4,6
 2,3,5,6
 3,4,5,6

【讨论】:

以上是关于SQL 和唯一的 n 列组合的主要内容,如果未能解决你的问题,请参考以下文章

R - 给定一个矩阵和一个幂,生成多个矩阵,其中包含矩阵列的所有唯一组合

组合 3 个表,其中 2 列的组合不是唯一的

如何为 Oracle 中的列组合赋予唯一约束?

使用 SQL 计数组合 [关闭]

索引之单列索引和组合索引

主键约束是啥和啥组合?