2010-05-14 228 views
2

我正在尋找一種按字母順序排列字符在varchar2中的函數。按字母順序在varchar2中對字符進行排序

是否有內置於oracle的內容,我可以使用或我需要在PL/SQL中創建自定義?

+0

所以如果你的列值是 選擇'CAB'從雙 它會返回'ABC'? – EvilTeach 2010-05-14 16:12:06

+0

這是正確的。 – mtim 2010-05-14 16:15:50

回答

1

http://forums.oracle.com/forums/thread.jspa?messageID=1791550這可能工作,但不擁有10g來測試的答案...

SELECT MIN(permutations) 
FROM (SELECT REPLACE (SYS_CONNECT_BY_PATH (n, ','), ',') permutations 
    FROM (SELECT LEVEL l, SUBSTR ('&col', LEVEL, 1) n 
     FROM DUAL 
     CONNECT BY LEVEL <= LENGTH ('&col')) yourtable 
    CONNECT BY NOCYCLE l != PRIOR l) 
WHERE LENGTH (permutations) = LENGTH ('&col') 

在這個例子中col是在SQL * Plus定義的,但如果你把這個函數你可以傳入它,或者可以直接將它改寫成表格列。

我會以此爲出發點而不是解決方案;最初的問題是關於anagrams,所以它被設計爲查找所有的排列,所以類似但簡化的東西可能是可能的。我懷疑這對於大數值並不能很好地擴展。

0

假設你不介意的人物每行返回1:

select substr(str, r, 1) X from (
select 'CAB' str, 
     rownum r 
from dual connect by level <= 4000 
) where r <= length(str) order by X; 

X 
= 
A 
B 
C 
0

你應該記住,沒有共同的協議是什麼「字母」的意思。這完全取決於它是哪個國家,誰在查看你的數據以及它處於什麼背景。

例如在DK中,有大量不同的a,a,b,c, ,O,A

  • 每字母表:A,AA,b,C,æ,O,A
  • 一些字典:A,AA,A,b,C,æ,ø
  • 對於其他字典:a,b,c,æ,ø,aa,
  • 按照Microsoft標準:a,b,c,æ,ø,aa,å

查看更多信息http://www.siao2.com/2006/04/27/584439.aspx。這也是碰巧成爲這些問題的好博客。

0

因此,最終我去了PL/SQL路由,因爲經過一段時間的搜索後,我意識到沒有可以使用的內置函數。

這是我想出來的。它基於關聯數組的未來,即Oracle按照排序順序保存鍵。

create or replace function sort_chars(p_string in varchar2) return varchar deterministic 
as 
    rv varchar2(4000); 
    ch varchar2(1); 
    type vcArray is table of varchar(4000) index by varchar2(1); 
    sorted vcArray; 

    key varchar2(1); 

begin 
    for i in 1 .. length(p_string) 
    loop 
     ch := substr(p_string, i, 1); 

     if (sorted.exists(ch)) 
     then 
      sorted(ch) := sorted(ch) || ch; 
     else 
      sorted(ch) := ch; 
     end if; 
    end loop; 


    rv := ''; 
    key := sorted.FIRST; 
    WHILE key IS NOT NULL LOOP 
     rv := rv || sorted(key); 
     key := sorted.NEXT(key); 
    END LOOP; 

    return rv; 
end; 

簡單的性能測試:

set timing on; 

create table test_sort_fn as 
select t1.object_name || rownum as test from user_objects t1, user_objects t2; 

select count(distinct test) from test_sort_fn; 

select count (*) from (select sort_chars(test) from test_sort_fn); 


Table created. 
Elapsed: 00:00:01.32 

COUNT(DISTINCTTEST) 
------------------- 
      384400 
1 row selected. 
Elapsed: 00:00:00.57 

    COUNT(*) 
---------- 
    384400 
1 row selected. 
Elapsed: 00:00:00.06 
0

您可以使用下面的查詢:

select listagg(letter) 
    within group (order by UPPER(letter), ASCII(letter) DESC) 
from 
(
select regexp_substr('gfedcbaGFEDCBA', '.', level) as letter from dual 
connect by regexp_substr('gfedcbaGFEDCBA', '.', level) is not null 
); 

子查詢拆分使用REGEXP_SUBSTR串入記錄(每一個單個字符),和外部查詢將記錄合併爲一個字符串,使用listagg,排序後。

這裏您應該小心,因爲按照Cine指出,按字母排序取決於數據庫配置。

在上面的例子中,字母按「按字母順序排列」並按ascii代碼降序排列,在我的情況下,結果爲「aAbBcCdDeEfFgG」。 您的情況可能會有所不同。

您也可以使用nlssort對信件進行排序 - 它可以更好地控制排序順序,因爲您可以獨立於數據庫配置。

select listagg(letter) 
    within group (order by nlssort(letter, 'nls_sort=german') 
from 
(
select regexp_substr('gfedcbaGFEDCBA', '.', level) as letter from dual 
connect by regexp_substr('gfedcbaGFEDCBA', '.', level) is not null 
); 

上面的查詢會給你也是「aAbBcCdDeEfFgG」,但如果你改變了「德國」,以「西班牙」,你會得到「AaBbCcDdEeFfGg」代替。