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

How do I use "not rlike" in spark-sql?

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 ?

没有什么不是 rlike,但在正则表达式中你有一个叫做负前瞻的东西,这意味着它会给出不匹配的词。

对于上述查询,您可以使用如下正则表达式。比方说,您希望 ColumnB 不应以数字“0”

开头

那你可以这样做。

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

我的意思是,您必须自己使用正则表达式来否定匹配,而不是 rlike。 Rlike 只是匹配您要求匹配的正则表达式。如果您的正则表达式告诉它不匹配,它适用,如果您的正则表达式用于匹配,那么它会那样做。

我知道你的问题有点老了,但以防万一:你试过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)

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

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

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

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

在 PySpark 中执行此操作的简洁方法是:

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