Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Oracle - string combinatorial permutation

I think I have a complex requirement.

It's a combinatorial permutation using Oracle 10.2, I'was able to solve it using cartesian joins, but I think that it need some improvements to made it simplest and more flexible.

Main behaviour.

input string: 'one two'

output: 'one' 'two' 'one two' 'two one'

For my solution I've restricted the number of strings to 5 (note that the output is a number near the 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
like image 352
Metl Avatar asked Aug 02 '11 18:08

Metl


1 Answers

Edit: Got the generic one. Really simple in the end (but took me a while to get there)

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: Removed redundant maxnum stuff. Left over from previous attempts

like image 111
Sodved Avatar answered Nov 08 '22 11:11

Sodved