2014-01-20 55 views
2

我正在嘗試通過應用篩選條件來標識僅列的數字,從而在表格中排列SELECT。這是一個僅用於報告的查詢,所以我們最不打擾的是性能,因爲我們沒有編譯PL/SQL的特權,無法通過TO_NUMBER()進行檢查,如果它是數字或不是數字,則返回。使用列中的數字只對數據進行篩選SQL

我必須在SQL中實現它。此外,該列具有這樣的值,必須將其視爲數字。

-1.0 
-0.1 
-.1 
+1,2034.89 
+00000 
1023 

突破性的研究之後,我寫了這一點。(硬時間)

WITH dummy_data AS 
    (SELECT '-1.0' AS txt FROM dual 
    UNION ALL 
    SELECT '+0.1' FROM dual 
    UNION ALL 
    SELECT '-.1' FROM dual 
    UNION ALL 
    SELECT '+1,2034.89.00' FROM dual 
    UNION ALL 
    SELECT '+1,2034.89' FROM dual 
    UNION ALL 
    SELECT 'Deva +21' FROM dual 
    UNION ALL 
    SELECT '1+1' FROM dual 
    UNION ALL 
    SELECT '1023' FROM dual 
) 
SELECT dummy_data.*, 
    REGEXP_COUNT(txt,'.') 
FROM dummy_data 
WHERE REGEXP_LIKE (TRANSLATE(TRIM(txt),'+,-.','0000'),'^[-+]*[[:digit:]]'); 

我得到了這一點。

TXT   REGEXP_COUNT(TXT,'.') 
------------- --------------------- 
-1.0        4 
+0.1        4 
-.1        3 
+1,2034.89.00     13 /* Should not be returned */ 
+1,2034.89      10 
1+1        3 /* Should not be returned */ 
1023        4 

7 rows selected. 

現在非常困惑與2個問題。

1)我得到+1,2034.89.00結果,我應該消除它。 (意思是小數點後兩位)不是小數點,所有其他特殊字符( - +,)的兩倍都應該被消除)

2)爲了使它更醜,計劃做一個REGEXP_COUNT('.') <= 1。但它沒有返回我的期望,而選擇它,我看到奇怪的價值觀返回。

有人可以幫我去框定爲REGEXP('.','+','-')

+0

http://stackoverflow.com/questions/5666986/how-can-i-determine-if-a-string-is-numeric-in-sql – OraNob

+0

'REGEXP_COUNT(」。')'統計字符串中的所有字符。所以它應該是'REGEXP_COUNT('\。')' –

回答

0

我只是想糾正你的錯誤並儘可能簡化了SQL。但不夠整齊!

WITH dummy_data AS 
    (SELECT '-1.0' AS txt FROM dual 
    UNION ALL 
    SELECT '+.0' FROM dual 
    UNION ALL 
    SELECT '-.1' FROM dual 
    UNION ALL 
    SELECT '+1,2034.89.0' FROM dual 
    UNION ALL 
    SELECT '+1,2034.89' FROM dual 
    UNION ALL 
    SELECT 'Deva +21' FROM dual 
    UNION ALL 
    SELECT 'DeVA 234 Deva' FROM dual 
    UNION ALL 
    SELECT '1023' FROM dual 
) 
SELECT to_number(REPLACE(txt,',')), 
    REGEXP_COUNT(txt,'.') 
FROM dummy_data 
WHERE REGEXP_LIKE (txt,'^[-+]*') 
AND NOT REGEXP_LIKE (TRANSLATE(txt,'+,-.','0000'),'[^[:digit:]]') 
AND REGEXP_COUNT(txt,',') <= 1 
AND REGEXP_COUNT(txt,'\+') <= 1 
AND REGEXP_COUNT(txt,'\-') <= 1 
AND REGEXP_COUNT(txt,'\.') <= 1; 
1

首先刪除加避免雙重OCCURENCES和減去與翻譯,然後你想知道爲什麼他們的位置不考慮? :-)

這應該工作:

WITH dummy_data AS 
    (SELECT '-1.0' AS txt FROM dual 
    UNION ALL 
    SELECT '+0.1' FROM dual 
    UNION ALL 
    SELECT '-.1' FROM dual 
    UNION ALL 
    SELECT '+12034.89.00' FROM dual -- invalid: duplicate decimal separator 
    UNION ALL 
    SELECT '+1,2034.89' FROM dual -- invalid: thousand separator placement 
    UNION ALL 
    SELECT 'Deva +21' FROM dual -- invalid: letters 
    UNION ALL 
    SELECT '1+1' FROM dual -- invalid: plus sign placement 
    UNION ALL 
    SELECT '1023' FROM dual 
    UNION ALL 
    SELECT '1.023,88' FROM dual -- invalid: decimal/thousand separators mixed up 
    UNION ALL 
    SELECT '1,234' FROM dual 
    UNION ALL 
    SELECT '+1,234.56' FROM dual 
    UNION ALL 
    SELECT '-123' FROM dual 
    UNION ALL 
    SELECT '+123,0000' FROM dual -- invalid: thousand separator placement 
    UNION ALL 
    SELECT '+234.' FROM dual -- invalid: decimal separator not followed by digits 
    UNION ALL 
    SELECT '12345,678' FROM dual -- invalid: missing thousand separator 
    UNION ALL 
    SELECT '+' FROM dual -- invalid: digits missing 
    UNION ALL 
    SELECT '.' FROM dual -- invalid: digits missing 
) 
select * from dummy_data 
where regexp_like(txt, '[[:digit:]]') and 
(
    regexp_like(txt, '^[-+]{0,1}([[:digit:]]){0,3}(\,([[:digit:]]){0,3})*(\.[[:digit:]]+){0,1}$') 
    or 
    regexp_like(txt, '^[-+]{0,1}[[:digit:]]*(\.[[:digit:]]+){0,1}$') 
); 

你看,你需要三個正則表達式;一個用於保證字符串中至少有一個數字,一個用於具有千位分隔符的數字,另一個用於沒有數字的數字。

使用千位分隔符:txt可以以一個加號或減號開頭,然後可以有三位數字。這些後面可能會有幾千個分隔符加上三個數字。然後可能會有一個小數分隔符,至少包含一個跟隨的數字。

沒有千分隔符:txt可能以一個加號或減號開始,然後可能會有數字。然後可能會有一個小數分隔符,至少包含一個跟隨的數字。

我希望我沒有忽視任何東西。

1

下面的表達式適用於一切,除了逗號:

'^[-+]*[0-9,]*[.]*[0-9]+$' 

您可以檢查與像其他檢查壞逗號位置:

not regexp_like(txt, '[-+]*,$') and not regexp_like(txt, [',,']) 
相關問題