如何在 spark-sql 中使用"not rlike"?



rlike工作正常,但not rlike抛出错误:

scala> sqlContext.sql("select * from T where columnB rlike '^[0-9]*$'").collect()
res42: Array[org.apache.spark.sql.Row] = Array([412,0], [0,25], [412,25], [0,25])
scala> sqlContext.sql("select * from T where columnB not rlike '^[0-9]*$'").collect()
java.lang.RuntimeException: [1.35] failure: ``in'' expected but `rlike' found

val df = sc.parallelize(Seq(
  (412, 0),
  (0, 25), 
  (412, 25), 
  (0, 25)
)).toDF("columnA", "columnB")

或者是问题的延续https://issues.apache.org/jira/browse/SPARK-4207?

在PySpark中实现这一点的一种简洁方法是:

df.filter(~df.column.rlike(pattern))

没有什么不是rlike,但在regex中,有一种叫做负前瞻的东西,这意味着它会给出不匹配的单词。

对于上述查询,您可以使用如下regex。比方说,你希望列B不应该以数字"0"开头

然后你可以这样做。

sqlContext.sql("select * from T where columnB rlike '^(?!.*[1-9]).*$'").collect() 
Result: Array[org.apache.spark.sql.Row] = Array([412,0])

总的来说,我的意思是,你必须用正则表达式本身来否定匹配,而不是用rlike。Rlike只是匹配您要求匹配的正则表达式。如果您的regex告诉它不匹配,它会应用它,如果您的正则表达式是用于匹配的,那么它会这样做。

以上答案建议使用负面前瞻。在某些情况下可以实现。然而,regexp的设计并不是为了进行有效的负匹配。这些正则表达式很容易出错,而且很难阅读。

Spark从2.0版本开始就支持"not rlike"。

 # given 'url' is column on a dataframe
 df.filter("""url not rlike "stackoverflow.com"""")

我唯一知道的用法是sql字符串表达式(如上所述)。我在python api中找不到"not"sql dsl函数。scala中可能有一个。

我知道你的问题有点老了,但以防万一:你只是试过scala的一元"!"运算符吗?

在java中,你会使用类似的方法:

DataFrame df = sqlContext.table("T");
DataFrame notLikeDf = df.filter(
  df.col("columnB").rlike("^[0-9]*$").unary_$bang()
);

在pyspark中,我是这样做的:

df = load_your_df()
matching_regex = "yourRegexString"
matching_df = df.filter(df.fieldName.rlike(matching_regex))
non_matching_df = df.subtract(matching_df)

相关内容

  • 没有找到相关文章

最新更新