2011-05-07 15 views
7

¿Hay una forma simple en Oracle de consultar combinaciones únicas de n campos? Tengo muy simple solución de dos campos:SQL y combinaciones únicas de n-coulmn

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

Consultando combinaciones únicas:

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); 

De esta consulta 1,2 y 2,1 se consideran la misma. Desafortunadamente no funciona para la estructura de 3 campos (por ejemplo, 1,2,3 debe considerarse igual a 3,1,2 porque el orden de los valores no importa). ¿Las funciones analíticas de Oracle proporcionan una solución adecuada para esta pregunta? ¿Podría sugerir alguna función analítica de Oracle en particular?

+1

¿No solo necesita unirse utilizando '<' en lugar de '<>'? –

Respuesta

6

su consulta para 2 columnas podría reescribirse así:

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

Para 3 columnas que entonces necesitaría hacer algunas adiciones (resaltado en negrita):

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 

Estoy seguro de que ahora puede adivinar cómo escalar esto para obtener más columnas.

0

Su solución consiste en utilizar un pipelined table function para devolver sus combinaciones.

Su función puede vivir en su propio paquete (con estado de paquete) que devuelve los datos que necesita, en el orden que desee. El estado sería un conjunto de variables determinadas por el número de columnas a devolver, inicializadas a los valores de inicio iniciales (A = 1, B = A + 1, C = B + 1, D = C + 1, etc.). Entonces usted simplemente

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 

Este salidas, para 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 
Cuestiones relacionadas