【问题标题】:Filter the rows with number only data in a column SQL过滤列 SQL 中只有数字数据的行
【发布时间】:2014-01-21 19:27:03
【问题描述】:

我正在尝试SELECT 表中的行,方法是应用仅识别数字列的过滤条件。这是一个仅报告的查询,因此我们对性能的影响最小,因为我们无权编译 PL/SQL,无法通过 TO_NUMBER() 检查并返回它是否为数字。

我必须在 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框起来,以避免('.','+','-')的双重出现

【问题讨论】:

标签: sql regex oracle


【解决方案1】:

以下表达式适用于除逗号之外的所有内容:

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

您可以通过以下附加检查来检查逗号位置是否错误:

not regexp_like(txt, '[-+]*,$') and not regexp_like(txt, [',,'])

【讨论】:

    【解决方案2】:

    首先你用翻译删除加号和减号,然后你想知道为什么不考虑它们的位置? :-)

    这应该可行:

    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 可能以一个加号或减号开头,然后可能有数字。那么可能会有一个小数分隔符,后面至少有一个数字。

    我希望我没有忽略任何事情。

    【讨论】:

      【解决方案3】:

      我只是试图纠正你的错误,并使 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;
      

      【讨论】:

        猜你喜欢
        • 2016-02-08
        • 2021-01-05
        • 2022-11-13
        • 2021-10-15
        • 1970-01-01
        • 2022-10-13
        • 1970-01-01
        • 1970-01-01
        • 2018-06-28
        相关资源
        最近更新 更多