2011-08-02 13 views
6

Creo que tengo un requisito complejo.Oráculo - permutación combinatoria de cadena

Es una permutación combinatoria utilizando Oracle 10.2, pude resolverlo usando uniones cartesianas, pero creo que es necesario algunas mejoras para hacerlo más simple y más flexible.

Comportamiento principal.

cadena entrada: 'uno dos'

salida: 'uno' 'dos' 'uno dos' 'dos ​​uno'

Por mi solución que he restringido el número de cadenas a 5 (tenga en cuenta que la salida es un número cerca del factorial)

SQL:

with My_Input_String as (select 1 as str_id, 'alpha beta omega gama' as str from dual) 

--------logic------- 

, String_Parse as (
        SELECT REGEXP_SUBSTR(str, '[^ ]+', 1, ROWNUM) str 
        FROM My_Input_String 
        where rownum < 6 -- string limitation -- 
        CONNECT BY level <= LENGTH(REGEXP_REPLACE(str, '([^ ])+|.', '\1')) 
       )  

--------CRAP select need refactoring------- 

select str from String_Parse 
union 
select REGEXP_REPLACE(trim(s1.str||' '||s2.str||' '||s3.str||' '||s4.str||' '||s5.str), '(){2,}', ' ') as str 
from 

(select str from String_Parse union select ' ' from dual) s1, 
(select str from String_Parse union select ' ' from dual) s2, 
(select str from String_Parse union select ' ' from dual) s3, 
(select str from String_Parse union select ' ' from dual) s4, 
(select str from String_Parse union select '  ' from dual) s5 
where 
-- 
s1.str <> s2.str and s1.str <> s3.str and s1.str <> s4.str and s1.str <> s5.str 
-- 
and s2.str <> s3.str and s2.str <> s4.str and s2.str <> s5.str 
-- 
and s3.str <> s4.str and s3.str <> s5.str 
-- 
and s4.str <> s5.str 
+2

¿Tiene que estar en SQL o también puede usar plsql? – Rene

+1

¿Va a tener un número fijo de elementos de cuerda? Porque si puede variar, entonces no veo cómo evitar ir por la ruta PL/SQL. El uso de la palabra "flexible" sugiere que eso es lo que estás pensando. – APC

+0

sí, se puede hacer usando plsql. – Metl

Respuesta

8

Editar: Tengo el genérico. Muy simple en el extremo (pero me tomó un tiempo para llegar allí)

WITH words AS 
( SELECT REGEXP_SUBSTR('&txt', '\S+', 1, LEVEL) AS word 
     , LEVEL          AS num 
    FROM DUAL 
    CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE('&txt', '\S+\s*', 'X')) 
) 
SELECT SYS_CONNECT_BY_PATH(W.word, ' ') 
FROM words W 
CONNECT BY NOCYCLE PRIOR W.num != W.num 

Edit2: Se ha eliminado la materia MAXNUM redundante. Dejados de intentos anteriores

+0

¡gran solución, justo lo que necesitaba! – Metl

+0

muy buena idea – josephj1989