首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Spark SQL的where子句排除空值

Spark SQL的where子句排除空值
EN

Stack Overflow用户
提问于 2015-12-06 20:00:23
回答 2查看 11.2K关注 0票数 4

我正在尝试在Apache spark sql上运行查询。第一个查询运行良好,但第二个查询也删除了空值。

代码:

代码语言:javascript
复制
def main(args: Array[String]) {

    val sc = new SparkContext("local[*]", "Spark")
    val sqlContext = new SQLContext(sc)

    val pageViewsDF = getDataframe(sc, sqlContext)

    println("RUNNING SQL QUERIES ")

    sqlContext.sql("select name , count(*) from pageviews_by_second group by name").show(10)

    sqlContext.sql("select name , count(*) from pageviews_by_second where name not in (\"Rose\") group by name").show(10)

  }

  def getDataframe(sc: SparkContext, sqlContext: SQLContext): DataFrame = {

    Logger.getLogger("org").setLevel(Level.OFF);
    Logger.getLogger("akka").setLevel(Level.OFF);

    val dataArray = List(List("David", null),
      List("David", null),
      List("Charlie", "23"),
      List("Rose", null),
      List("Ben", null),
      List("Harry", "43"),
      List(null, "25"),
      List(null, "21"),
      List("David", "15"),
      List("Rose", null),
      List("Alan", "26"))
    val separator = ","

    // Create an RDD
    val dataRDD = sc.parallelize(dataArray)

    // The schema is encoded in a string
    val header = "name,age"

    // Import Spark SQL data types and Row.
    import org.apache.spark.sql._

    // Generate the schema based on the string of schema
    val schema =
      StructType(
        header.split(separator).map { fieldName =>
          StructField(fieldName, StringType, true)
        })

    val rowRDD =
      dataRDD
        .map(p => Row(p(0), p(1)))

    // Apply the schema to the RDD.
    var df = sqlContext.createDataFrame(rowRDD, schema)

    df.registerTempTable("pageviews_by_second")

    df
  }

第一次查询的结果是:

代码语言:javascript
复制
+-------+---+
|   name|_c1|
+-------+---+
|   Alan|  1|
|    Ben|  1|
|  David|  3|
|Charlie|  1|
|   Rose|  2|
|  Harry|  1|
|   null|  2|
+-------+---+

和第二个查询的输出:

代码语言:javascript
复制
+-------+---+
|   name|_c1|
+-------+---+
|   Alan|  1|
|    Ben|  1|
|  David|  3|
|Charlie|  1|
|  Harry|  1|
+-------+---+

在第二个查询中,我只排除了"Rose“,但也排除了"null”。

如果我的查询是错误的,请帮助我进行正确的查询。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-12-06 20:31:33

这是因为SQL中的NULL等同于“未知”。这意味着除了IS NULL / IS NOT NULL之外,任何与NULL的比较都是未定义的,并返回NULL

代码语言:javascript
复制
case class Record(id: Integer, value: String)

val df = sc.parallelize(Seq(Record(1, "foo"), Record(2, null))).toDF
df.registerTempTable("df")

sqlContext.sql("""SELECT value = "foo" FROM df""").show
// +----+
// | _c0|
// +----+
// |true|
// |null|
// +----+

sqlContext.sql("""SELECT value != "foo" FROM df""").show
// +-----+
// |  _c0|
// +-----+
// |false|
// | null|
// +-----+

因此,IN / NOT IN也是未定义的:

代码语言:javascript
复制
sqlContext.sql("""SELECT value IN ("foo", "bar")  FROM df""").show
// +----+
// | _c0|
// +----+
// |true|
// |null|
// +----+

这是一个标准的SQL行为,正确实现SQL标准的系统应该以同样的方式运行。如果你要过滤并保留NULLs,你必须显式地设置它:

代码语言:javascript
复制
sqlContext.sql(
  """SELECT value IN ("foo", "bar") OR value IS NULL FROM df""").show
// +----+
// | _c0|
// +----+
// |true|
// |true|
// +----+
票数 7
EN

Stack Overflow用户

发布于 2015-12-06 20:52:33

如果希望切换回两种状态逻辑,则需要将可为空的列(这是专有NVL的标准术语) coalesce为某个不存在的值。

使用与@zero323相同的设置

代码语言:javascript
复制
 sqlContext.sql("""SELECT value, coalesce(value,'other baz') = "foo" FROM df""").show

代码语言:javascript
复制
value c1
foo   true
null  false
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34117167

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档