【问题标题】:SQL Server's isNumeric() equivalent in amazon redshift亚马逊红移中 SQL Server 的 isNumeric() 等效项
【发布时间】:2013-06-01 15:34:15
【问题描述】:
  • 我使用 amazon redshift 作为我的数据仓库
  • 我有一个字符串类型的字段 (field1)。有些字符串以四个数字开头,有些则以字母开头:

'测试 alpha'
'1382 测试版'

  • 我想过滤掉字符串不以四个数字开头的行
  • 查看 redshift 文档,我不认为 isnumber 或 isnumeric 是函数。似乎“喜欢”功能是最好的可能性。
  • 我试过了

    where left(field1, 4) like '[0-9][0-9][0-9][0-9]'

这不起作用,从下面的链接看来,redshift 可能不支持:

https://forums.aws.amazon.com/message.jspa?messageID=439850

'where' 子句中是否有错误?如果不是,并且 redshift 不支持该子句,有没有办法过滤?我正在考虑使用演员表

cast(left(field1,4) as integer) 

然后如果它产生错误则传递该行,但不确定如何在亚马逊红移中执行此操作。或者是否有其他用于非数字过滤器的代理。

谢谢

【问题讨论】:

  • 您的示例不适用于 PostgreSQL。 ILIKE 不支持正则表达式。 Amazon Redshift 基于 PostgreSQL 8.0.2,所以也许您可以使用 SIMILAR 运算符 postgresql.org/docs/8.0/interactive/… REGEXP 因为 SIMILAR 是关键字,也许......有些像 SELECT substring('1234 xxx' FROM 1 FOR 4) 类似于 '[\d] {4}';

标签: amazon-redshift


【解决方案1】:

尝试类似:

where field1 ~ '^[0-9]{4}'

它将匹配任何以 4 位数字开头的字符串。

【讨论】:

  • 感谢伊戈尔和帕维尔。不幸的是,上面的内容似乎不适用于红移。以下声明:
  • 抱歉,评论被截断了……感谢 Igor 和 Pavel。不幸的是,上面的内容似乎不适用于红移。当我在语句中添加 'where field1 ~ '^[0-9]{4}'' 子句时,语句返回:'ERROR: Regular Expression Matching is not supported [SQL State=XX000]'。如果我尝试 'where field1 like '^[0-9]{4}'' 它返回一个空表,但没有错误。如果我尝试 'where field1 like '$'' 它会返回所有行。似乎 redshift 只支持“like”,但不支持表达式的其余部分。有任何想法吗?再次感谢。
  • 如果你想仔细看看,这里是关于'like'的红移文档的链接:docs.aws.amazon.com/redshift/latest/dg/…>
  • 目前(10 月 16 日)此语句在 Redshift 查询中起作用
【解决方案2】:

redshift 似乎不支持以下任何一项:

where left(field1,4) like '[0-9][0-9][0-9][0-9]' 
where left(field1,4) ~ '^[0-9]{4}'
where left(field1,4) like '^[0-9]{4}'

似乎有效的是:

where left(field1,4) between 0 and 9999

这将返回以四个数字字符开头的所有行。

似乎即使 field1 是字符串类型,'between' 函数在字符串字符为数字时将 left(field1,4) 解释为单个整数(并且在它们不是数字时不会给出错误)。如果我发现问题,我会跟进。例如,我不处理小于 1000 的任何内容,因此我假设但不确定 0001 被解释为 1。

【讨论】:

  • 我不认为这是正确的。举以下示例:select count(*) from a where thing = '3081_xl7' and thing between 0 and 999999; 这将返回 1。在这种情况下,thing 是一个 varchar 列。
【解决方案3】:

看起来您要查找的代码是 similar to 函数:

where left(field,4) similar to '[0-9]{4}'

Redshift doc

【讨论】:

  • 这个对我来说效果很好,除了你必须使用撇号: where left(field,4) 类似于 '[0-9]{4}'
【解决方案4】:
where regexp_instr(field1,'^[0-9]{4}') = 0

将删除以 4 位开头的行(上面的 regexp_instr 将为 field1 以 4 位开头的行返回 1)

【讨论】:

    【解决方案5】:

    尽管自提出这个问题以来已经过去了很长时间,但我还没有找到足够的答案。所以我觉得有义务分享我的解决方案,该解决方案在我今天(2016 年 3 月)的 Redshift 集群上运行良好。

    UDF函数为:

    create or replace function isnumeric (aval VARCHAR(20000))
      returns bool
    IMMUTABLE 
    as $$
        try:
           x = int(aval);
        except:
           return (1==2);
        else:
           return (1==1);
    $$ language plpythonu;
    

    用法如下:

    select isnumeric(mycolumn), * from mytable
        where isnumeric(mycolumn)=false
    

    【讨论】:

    • 应该是最佳答案
    【解决方案6】:

    我们已经尝试了以下方法并在我们的大多数场景中工作:

    columnn ~ '^[-]{0,1}[0-9]{1,}[.]{0,1}[0-9]{0,}$'

    这将是正数、负数、整数和浮点数。

    【讨论】:

      【解决方案7】:

      根据亚马逊,posix 风格 ~regex 风格的表达很慢...... https://docs.aws.amazon.com/redshift/latest/dg/pattern-matching-conditions.html

      使用他们自己的REGEXP_* 函数似乎更快。 https://docs.aws.amazon.com/redshift/latest/dg/String_functions_header.html

      为了检查整数的真/假,我一直在成功使用以下方法。 REGEXP_COUNT(my_field_to_check, '^[0-9]+$') > 0

      如果只有数字则返回 1,否则返回 0

      【讨论】:

        【解决方案8】:

        redshift应该支持类似的。

        WHERE field1 SIMILAR TO '[0-9]{4}%'
        

        这读作 field1 以 0-9 范围内的 4 个字符开头,然后是其他字符。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-04-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-05-26
          • 1970-01-01
          相关资源
          最近更新 更多