【问题标题】:Test for numeric value?测试数值?
【发布时间】:2011-12-19 17:48:37
【问题描述】:

我们在临时表中加载的供应商数据相当脏。特别是一列捕获数字数据,但 40% 的时间包含垃圾字符或随机字符串。

我必须创建一个过滤掉该列中值范围的报告。所以,我尝试像这样使用替换/翻译的组合

select replace(translate(upper(str),' ','all possible char'),' ','')
from table

但只要遇到我没有编码的字符,它就会失败。因此,报告永远无法自动化。

Javascript 有 isNaN() 函数来判断一个值是否为非法数字(如果是,则为 True,否则为 false)。

我怎样才能用 DB2 做同样的事情?你有什么想法吗?

提前致谢。

【问题讨论】:

    标签: db2


    【解决方案1】:

    一种相当可靠(但有点老套)的方法是将字符串与其大写和小写自身进行比较(数字没有不同的大小写)。只要您引入字符的数据仅包含拉丁字符,就可以了:

    SELECT input, CASE
        WHEN UPPER(input) = LOWER(input) THEN TO_NUMBER(input)
        ELSE 0
    END AS output
    FROM source
    

    另一种选择是使用TRANSLATE 函数:

    SELECT input,
        CASE 
            WHEN TRANSLATE(CAST(input as CHAR(10)), '~~~~~~~~~~~~~', '0123456789-. ') = '~~~~~~~~~~' THEN CAST(input AS DECIMAL(12, 2))
            ELSE 0
        END AS num
    FROM x
    

    【讨论】:

    • 这种方法会不正确地接受包含标点字符的字符串。
    • @FredSobotka:我添加了第二个可能更好的选项......它对数据长度做了一些假设,但可以调整这些假设。
    • @galador:接受并投票。似乎最适合我们的数据。更广泛的案例陈述炸弹。
    【解决方案2】:
    WITH x (stringval) AS 
    (
    VALUES ('x2'),(''),('2.2.'),('5-'),('-5-'),('--5'),('.5'),('2 2'),('0.5-'),(' 1 '),('2  '),('3.'),('-4.0')
    )
    SELECT stringval,
    CASE WHEN (
    
    -- Whitespace must not appear in the middle of a number 
    -- (but trailing and/or leading whitespace is permitted)
    RTRIM(LTRIM( stringval )) NOT LIKE '% %'
    
    -- A number cannot start with a decimal point
    AND LTRIM( stringval ) NOT LIKE '.%'
    
    -- A negative decimal number must contain at least one digit between 
    -- the negative sign and the decimal point
    AND LTRIM( stringval ) NOT LIKE '-.%'
    
    -- The negative sign may only appear at the beginning of the number
    AND LOCATE( '-', LTRIM(stringval)) IN ( 0, 1 )
    
    -- A number must contain at least one digit
    AND TRANSLATE( stringval, '0000000000', '123456789') LIKE '%0%'
    
    -- Allow up to one negative sign, followed by up to one decimal point
    AND REPLACE( 
        TRANSLATE( RTRIM(LTRIM(stringval)), '000000000', '123456789'), 
        '0', '') IN ('','-','.','-.')
    )
    THEN 'VALID'
    ELSE 'INVALID'
    END AS stringisvalidnumber
    FROM x
    ;
    

    【讨论】:

    • 除了接受前导和尾随空格之外,它还是一套相当严格的测试。如果您想简化可接受的小数格式,以便不再需要小数点前面的数字,则可以省略 CASE 语句的第二个和第三个条件。
    【解决方案3】:

    看看这个:

    SELECT Mobile, 
     TRANSLATE(Mobile, '~~~~~~~~~~', '0123456789') AS FirstPass, 
     TRANSLATE(TRANSLATE(Mobile, '~~~~~~~~~~', '0123456789'), '', '~') AS Erroneous, 
    REPLACE(TRANSLATE(Mobile, '', TRANSLATE(TRANSLATE(Mobile, '~~~~~~~~~~', '0123456789'), '', '~')), ' ', '') AS Corrected 
     FROM Person WHERE Mobile <> '' FETCH FIRST 100 ROWS ONLY
    

    表格是“Person”,您要检查的字段是“Mobile”。 如果你在这方面做更多的工作,你可以构建一个 UPDATE 来修复整个表

    【讨论】:

    • fyi:代码行需要 4 个前导空格 :-) 提示:格式化/标记帮助可用,只需在输入框中打问号即可。
    猜你喜欢
    • 2015-02-01
    • 2010-11-06
    • 1970-01-01
    • 1970-01-01
    • 2015-08-24
    • 2017-02-04
    • 2022-01-05
    • 1970-01-01
    • 2019-04-02
    相关资源
    最近更新 更多