2011-08-02 11 views
6

Sanırım karmaşık bir gereksinim var.Oracle - string combinatorial permutation

Bu, Oracle 10.2'yi kullanarak bir kombinatoryal permütasyon, kartezyen birleştirmeler kullanarak çözmeyi başarabiliyordum, ancak bunun en basit ve daha esnek olmasını sağlamak için bazı iyileştirmelere ihtiyaç duyduğunu düşünüyorum.

Ana davranış.

girdi dizesi: 'tek iki'

çıkış: 'iki' 'bir veya iki' 'iki bir' benim çözüm için

Ben sınırlandırdığınız 'tek' 5 olan dizelerin sayısı (çıktının fakültenin yakınında bir sayı olduğunu unutmayın)

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

SQL'de mi yoksa plsql'i de kullanabilir misiniz? – Rene

+1

Sabit sayıda dize elemanı var mı? Çünkü eğer değişiklik gösterebilirse, o zaman PL/SQL yolunu yapmaya nasıl devam edeceğinizi göremiyorum. "Esnek" kelimesini kullanmanız, düşündüğünüz şeyi gösterir. – APC

+0

evet, plsql kullanılarak yapılabilir. – Metl

cevap

8

Düzenleme: Genel olanı aldım. Gerçekten sonunda basit (ama oraya biraz zaman aldı)

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: gereksiz maxnum şeyler kaldırıldı. Önceki girişimlerden geriye kalanlar

+0

mükemmel çözüm, tam ihtiyacım olan şey! – Metl

+0

gerçekten iyi bir fikir – josephj1989