2011-05-07 51 views
7

Oracle有一種簡單的方法來查詢n個字段的唯一組合。我有很簡單的兩個領域解決方案:SQL和獨特的n-coulmn組合

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分析功能嗎?

+1

難道你只需要使用'<'而不是'<>'來連接? – 2011-05-07 22:17:00

回答

6

您的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 

我相信您現在可以輕鬆猜出如何爲更多列進行縮放。

0

您的解決方案在於使用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