如何在 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")
没有什么不是 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))
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")
没有什么不是 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))