【spark原理系列】 Column 原理用法示例源码分析

spark Column 原理用法示例源码分析

一、原理

Spark 的 Column 类是 Spark SQL 中用于表示列操作和表达式的核心类之一。它是一个不可变类,封装了对数据集中某一列的操作和转换。

Column 的实现原理主要依赖于 Spark SQL 的逻辑优化器和物理执行引擎。下面是 Column 类的几个关键特点和原理:

  1. 表达式树:Column 实际上是一个表达式树,其中每个节点代表一个操作或转换。例如,col("age") + 10 将生成一个二叉表达式树,其中根节点表示加法操作,左子节点表示 “age” 列,右子节点表示常量值 10。

  2. 逻辑优化器:Spark SQL 的逻辑优化器会对 Column 表达式树进行优化。它可以进行常量折叠、谓词下推、投影消除等优化,以提高查询性能和降低计算开销。

  3. Catalyst 编译器:Spark SQL 使用 Catalyst 编译器将 Column 表达式树转换为逻辑计划和物理计划。逻辑计划表示逻辑操作序列,而物理计划则表示如何在分布式环境下执行这些操作。

  4. 执行引擎:物理计划最终由 Spark 的执行引擎执行。执行引擎会将物理计划转换为一系列的 RDD 转换操作或 Spark SQL 内置的优化器,例如 Tungsten 等。这些操作最终被转换为 Spark 的执行图谱,并在分布式集群上执行。

通过以上的原理,Column 实现了对列的常见操作和转换,例如选择、过滤、聚合、排序、连接等。它提供了丰富的 API,使得用户可以方便地进行表达式计算和数据处理。

需要注意的是,Column 本身并不存储实际的数据,而只是表示对数据的操作和转换。它是一个惰性求值的结构,只有在真正需要结果时才会触发计算。

总结起来,Spark 的 Column 类通过表达式树、逻辑优化器、Catalyst 编译器和执行引擎实现了对列的操作和转换。它是 Spark SQL 中非常重要的组成部分,用于构建复杂的查询和数据处理任务。

二、用法总结

算术运算
  • *:乘法运算。
  • /:除法运算。
  • %:取模运算。
  • +:加法运算。
  • -:减法运算。
关系运算
  • <:小于比较。
  • <=:小于等于比较。
  • >:大于比较。
  • >=:大于等于比较。
  • ===:相等比较。
  • =!=:不等比较。
逻辑运算
  • &&:逻辑与运算。
  • ||:逻辑或运算。
  • !:逻辑非运算。
类型转换
  • cast:将列的数据类型转换为指定类型。
  • as[U : Encoder]:将列转换为具有指定类型的 TypedColumn。
字符串操作
  • startsWith:判断字符串是否以指定前缀开头。
  • endsWith:判断字符串是否以指定后缀结尾。
  • contains:判断字符串是否包含指定子字符串。
  • like:使用通配符模式进行匹配。
  • rlike:使用正则表达式进行匹配。
  • substr:获取字符串的子串。
集合操作
  • array:创建数组类型的字段。
  • map:创建映射类型的字段。
  • getItem:获取集合中指定索引位置的元素。
  • isInCollection:判断是否在给定的集合中。
排序和聚合
  • asc:升序排序。
  • desc:降序排序。
  • isNull:判断是否为空。
  • isNotNull:判断是否不为空。
  • over:用于窗口函数。
其他操作
  • alias:给列取别名。
  • name:给列取别名。
  • otherwise:当条件不满足时返回指定值。
  • when:根据条件选择值。
数值比较
  • eqNullSafe:安全相等比较,处理空值情况。
  • notEqual:不等比较。
数据类型操作
  • binary:创建二进制类型的字段。
  • boolean:创建布尔类型的字段。
  • byte:创建字节类型的字段。
  • date:创建日期类型的字段。
  • decimal:创建十进制类型的字段。
  • double:创建双精度浮点类型的字段。
  • float:创建单精度浮点类型的字段。
  • int:创建整型类型的字段。
  • long:创建长整型类型的字段。
  • short:创建短整型类型的字段。
  • string:创建字符串类型的字段。
  • timestamp:创建时间戳类型的字段。
列操作和别名
  • alias:给列取别名。
  • name:给列取别名。
  • getField:获取嵌套结构中的字段。
窗口函数和排序
  • over:用于窗口函数。
  • asc_nulls_first:升序排序,空值排在前面。
  • asc_nulls_last:升序排序,空值排在后面。
  • desc_nulls_first:降序排序,空值排在前面。
  • desc_nulls_last:降序排序,空值排在后面。
特殊操作
  • explain:解释执行计划。
  • isNaN:判断是否为NaN。
数值操作
  • bitwiseAND:按位与运算。
  • bitwiseOR:按位或运算。
  • bitwiseXOR:按位异或运算。
  • unary_-:取负运算。。

三、示例

package org.example.spark
import org.apache.spark.sql.expressions.Window
import org.apache.spark.sql.functions._
import org.apache.spark.sql.{Column, Encoders, SparkSession, TypedColumn}

object ColumnMethodsDemo {
  def main(args: Array[String]): Unit = {
    val spark = SparkSession.builder()
      .appName("ColumnMethodsDemo")
      .master("local")
      .getOrCreate()

    import spark.implicits._

    // 创建示例数据集
    val data = Seq(
      ("Alice", 25, "New York"),
      ("Bob", 30, "San Francisco"),
      ("Charlie", 35, "London")
    )
    val df = data.toDF("name", "age", "city")
    df.printSchema()

    // 算术运算
    val column1: Column = col("age") * 2
    val column2: Column = col("age") + 10
    val column3: Column = col("age") - 5
    val column4: Column = col("age") / 3
    val column5: Column = col("age") % 4
    df.select(column1,column2,column3,column4,column5).show(truncate = false)
//  +---------+----------+---------+------------------+---------+
//  |(age * 2)|(age + 10)|(age - 5)|(age / 3)         |(age % 4)|
//  +---------+----------+---------+------------------+---------+
//  |50       |35        |20       |8.333333333333334 |1        |
//  |60       |40        |25       |10.0              |2        |
//  |70       |45        |30       |11.666666666666666|3        |
//  +---------+----------+---------+------------------+---------+

    // 关系运算
    val column6: Column = col("age") < 30
    val column7: Column = col("age") <= 30
    val column8: Column = col("age") > 30
    val column9: Column = col("age") >= 30
    val column10: Column = col("age") === 30
    val column11: Column = col("age") =!= 30
    val column35: Column = col("age").eqNullSafe(30)
    val column36: Column = col("age").notEqual(30)
    df.select(column6,column7,column8,column9,column10,column11,column35,column36).show(truncate = false)
//  +----------+-----------+----------+-----------+----------+----------------+------------+----------------+
//  |(age < 30)|(age <= 30)|(age > 30)|(age >= 30)|(age = 30)|(NOT (age = 30))|(age <=> 30)|(NOT (age = 30))|
//  +----------+-----------+----------+-----------+----------+----------------+------------+----------------+
//  |true      |true       |false     |false      |false     |true            |false       |true            |
//  |false     |true       |false     |true       |true      |false           |true        |false           |
//  |false     |false      |true      |true       |false     |true            |false       |true            |
//  +----------+-----------+----------+-----------+----------+----------------+------------+----------------+

    // 逻辑运算
    val column12: Column = col("age")===10 && (col("city") === "New York")
    val column13: Column = col("age")===10 || (col("city") === "New York")
    val column14: Column = !( col("age") === 30)
    df.select(column12,column13,column14).show(truncate = false)
//  +----------------------------------+---------------------------------+----------------+
//  |((age = 10) AND (city = New York))|((age = 10) OR (city = New York))|(NOT (age = 30))|
//  +----------------------------------+---------------------------------+----------------+
//  |false                             |true                             |true            |
//  |false                             |false                            |false           |
//  |false                             |false                            |true            |
//  +----------------------------------+---------------------------------+----------------+

    // 类型转换
    val column15: Column = col("age").cast("double")
    // TypedColumn 类型操作
    val column151: TypedColumn[String, Double] = col("age").as[Double]
    // 编码器操作
    val encoder = Encoders.DOUBLE
    val column152  = col("age").as(encoder).alias("age2")
    df.select(column15,column151,column152).printSchema()
    df.select(column15,column151,column152).show(truncate = false)
//  df.select("age").as[Double].show()
//  df.select(col("age").as(encoder)).show()

//    |-- age: double (nullable = false)
//    |-- age: integer (nullable = false)
//    |-- age2: integer (nullable = false)
//
//    +----+---+----+
//    |age |age|age2|
//    +----+---+----+
//    |25.0|25 |25  |
//    |30.0|30 |30  |
//    |35.0|35 |35  |
//    +----+---+----+

    // 字符串操作
    val column16: Column = col("name").startsWith("A")
    val column17: Column = col("name").endsWith("e")
    val column18: Column = col("name").contains("li")
    val column19: Column = col("name").like("A%")
    val column20: Column = col("name").rlike("^A.*e$")
    val column21: Column = col("name").substr(2, 3)
    df.select(column16,column17,column18,column19, column20,column21  ).show(truncate = false)
//  +-------------------+-----------------+------------------+------------+-----------------+---------------------+
//  |startswith(name, A)|endswith(name, e)|contains(name, li)|name LIKE A%|name RLIKE ^A.*e$|substring(name, 2, 3)|
//  +-------------------+-----------------+------------------+------------+-----------------+---------------------+
//  |true               |true             |true              |true        |true             |lic                  |
//  |false              |false            |false             |false       |false            |ob                   |
//  |false              |true             |true              |false       |false            |har                  |
//  +-------------------+-----------------+------------------+------------+-----------------+---------------------+

    // 集合操作
    val column22: Column = array(col("age"), col("city"))
    val column23: Column = map(col("name"), col("age"))
    val column222: Column = map_from_arrays(column22,column22)
    df.select(column22,column23,column222).show(truncate = false)
//  +-------------------+---------------+---------------------------------------------------+
//  |array(age, city)   |map(name, age) |map_from_arrays(array(age, city), array(age, city))|
//  +-------------------+---------------+---------------------------------------------------+
//  |[25, New York]     |[Alice -> 25]  |[25 -> 25, New York -> New York]                   |
//  |[30, San Francisco]|[Bob -> 30]    |[30 -> 30, San Francisco -> San Francisco]         |
//  |[35, London]       |[Charlie -> 35]|[35 -> 35, London -> London]                       |
//  +-------------------+---------------+---------------------------------------------------+

    // 排序
    val column24: Column = col("age").asc
    val column25: Column = col("age").desc
    val column55: Column = col("age").asc_nulls_first
    val column56: Column = col("age").asc_nulls_last
    val column57: Column = col("age").desc_nulls_first
    val column58: Column = col("age").desc_nulls_last
    df.orderBy(column24).show()
    df.orderBy(column25).show()
    df.orderBy(column55).show()
    df.orderBy(column56).show()
    df.orderBy(column57).show()
    df.orderBy(column58).show()
//
//  +-------+---+-------------+
//  |   name|age|         city|
//  +-------+---+-------------+
//  |  Alice| 25|     New York|
//  |    Bob| 30|San Francisco|
//  |Charlie| 35|       London|
//  +-------+---+-------------+
//
//  +-------+---+-------------+
//  |   name|age|         city|
//  +-------+---+-------------+
//  |Charlie| 35|       London|
//  |    Bob| 30|San Francisco|
//  |  Alice| 25|     New York|
//  +-------+---+-------------+
//
//  +-------+---+-------------+
//  |   name|age|         city|
//  +-------+---+-------------+
//  |  Alice| 25|     New York|
//  |    Bob| 30|San Francisco|
//  |Charlie| 35|       London|
//  +-------+---+-------------+
//
//  +-------+---+-------------+
//  |   name|age|         city|
//  +-------+---+-------------+
//  |  Alice| 25|     New York|
//  |    Bob| 30|San Francisco|
//  |Charlie| 35|       London|
//  +-------+---+-------------+
//
//  +-------+---+-------------+
//  |   name|age|         city|
//  +-------+---+-------------+
//  |Charlie| 35|       London|
//  |    Bob| 30|San Francisco|
//  |  Alice| 25|     New York|
//  +-------+---+-------------+
//
//  +-------+---+-------------+
//  |   name|age|         city|
//  +-------+---+-------------+
//  |Charlie| 35|       London|
//  |    Bob| 30|San Francisco|
//  |  Alice| 25|     New York|
//  +-------+---+-------------+

    // when otherwise操作
     val column30df  = df.select( when(col("name") === "jess",0 ).otherwise(2).alias("whencol"))
    column30df.show()

//  +-------+
//  |whencol|
//  +-------+
//  |      2|
//  |      2|
//  |      2|
//  +-------+
    // 数值操作
    val column32: Column = col("age").bitwiseAND(5)
    val column33: Column = col("age").bitwiseOR(10)
    val column34: Column = -col("age")
    df.select(column32,column33,column34).show()

    // 集合操作
    val column37: Column = column22.getItem(0) //column22 array(col("age"), col("city"))
    val column38: Column = col("name").isInCollection(Seq("Alice", "Bob"))
    val column39: Column = col("name").isin(Seq("Alice", "Bob"):_*)
    df.select(column37,column38,column39).show()
//  +-----------------------------------+----------------------+----------------------+
//  |array(CAST(age AS STRING), city)[0]|(name IN (Alice, Bob))|(name IN (Alice, Bob))|
//  +-----------------------------------+----------------------+----------------------+
//  |                                 25|                  true|                  true|
//  |                                 30|                  true|                  true|
//  |                                 35|                 false|                 false|
//  +-----------------------------------+----------------------+----------------------+
    // 列操作和别名
    val column51: Column = col("name").alias("full_name")
    val column52: Column = col("name").name("full_name")
    val column53: Column = struct("name","age").getField("age")
    df.select(column51,column52,column53).show()
//  +---------+---------+--------------------------------------+
//  |full_name|full_name|named_struct(name, name, age, age).age|
//  +---------+---------+--------------------------------------+
//  |    Alice|    Alice|                                    25|
//  |      Bob|      Bob|                                    30|
//  |  Charlie|  Charlie|                                    35|
//  +---------+---------+--------------------------------------+

    // 窗口函数和排序
    val column54: Column = sum(col("age")).over(Window.partitionBy("name").orderBy("city"))
    val column28: Column = sum(col("age")).over()
    df.select(column54,column28).show()
//  +-----------------------------------------------------------------------------------+-----------------------------------+
//  |sum(age) OVER (PARTITION BY name ORDER BY city ASC NULLS FIRST unspecifiedframe$())|sum(age) OVER (unspecifiedframe$())|
//  +-----------------------------------------------------------------------------------+-----------------------------------+
//  |                                                                                 25|                                 90|
//  |                                                                                 30|                                 90|
//  |                                                                                 35|                                 90|
//  +-----------------------------------------------------------------------------------+-----------------------------------+
    // 特殊操作
    val column60: Column = col("age").isNaN
    val column26: Column = col("age").isNull
    val column27: Column = col("age").isNotNull
    df.select(column60,column26,column27).show()
//  +----------+-------------+-----------------+
//  |isnan(age)|(age IS NULL)|(age IS NOT NULL)|
//  +----------+-------------+-----------------+
//  |     false|        false|             true|
//  |     false|        false|             true|
//  |     false|        false|             true|
//  +----------+-------------+-----------------+
  }
}

四、中文源码

private[sql] object Column {

  // 创建一个Column对象,根据列名
  def apply(colName: String): Column = new Column(colName)

  // 创建一个Column对象,根据表达式
  def apply(expr: Expression): Column = new Column(expr)

  // 提取Column对象中的Expression对象
  def unapply(col: Column): Option[Expression] = Some(col.expr)

  // 生成Expression的别名
  private[sql] def generateAlias(e: Expression): String = {
    e match {
      case a: AggregateExpression if a.aggregateFunction.isInstanceOf[TypedAggregateExpression] =>
        a.aggregateFunction.toString
      case expr => toPrettySQL(expr)
    }
  }
}

/**
 * Column的泛型版本,用于指定输入类型和返回类型的Encoder。
 *
 * @tparam T 表达式的输入类型,如果表达式由分析器而不是编译器进行类型检查,则可以为`Any`(例如:`expr("sum(...)")`)
 * @tparam U 列的输出类型
 *
 * @since 1.6.0
 */
@InterfaceStability.Stable
class TypedColumn[-T, U](
    expr: Expression,
    private[sql] val encoder: ExpressionEncoder[U])
  extends Column(expr) {

  // 插入特定的输入类型和模式到预期对解码对象操作的任何表达式中
  private[sql] def withInputType(
      inputEncoder: ExpressionEncoder[_],
      inputAttributes: Seq[Attribute]): TypedColumn[T, U] = {
    val unresolvedDeserializer = UnresolvedDeserializer(inputEncoder.deserializer, inputAttributes)
    val newExpr = expr transform {
      case ta: TypedAggregateExpression if ta.inputDeserializer.isEmpty =>
        ta.withInputInfo(
          deser = unresolvedDeserializer,
          cls = inputEncoder.clsTag.runtimeClass,
          schema = inputEncoder.schema)
    }
    new TypedColumn[T, U](newExpr, encoder)
  }

  // 给TypedColumn指定一个名称(别名)
  override def name(alias: String): TypedColumn[T, U] =
    new TypedColumn[T, U](super.name(alias).expr, encoder)

}

/**
 * 在`DataFrame`中根据数据计算的列。
 *
 * 可以基于`DataFrame`中的输入列构建新的列:
 *
 * {{{
 *   df("columnName")            // 在特定的`df` DataFrame 上
 *   col("columnName")           // 一个尚未与任何DataFrame关联的通用列
 *   col("columnName.field")     // 提取结构体字段
 *   col("`a.column.with.dots`") // 转义列名中的`.`
 *   $"columnName"               // Scala中的命名列的简写方式
 * }}}
 *
 * 可以组合[[Column]]对象来形成复杂的表达式:
 *
 * {{{
 *   $"a" + 1
 *   $"a" === $"b"
 * }}}
 *
 * @note 内部Catalyst表达式可以通过[[expr]]访问,但此方法仅供调试目的,并且可能在任何Spark版本中更改。
 *
 * @since 1.3.0
 */
@InterfaceStability.Stable
class Column(val expr: Expression) extends Logging {

  def this(name: String) = this(name match {
    case "*" => UnresolvedStar(None)
    case _ if name.endsWith(".*") =>
      val parts = UnresolvedAttribute.parseAttributeName(name.substring(0, name.length - 2))
      UnresolvedStar(Some(parts))
    case _ => UnresolvedAttribute.quotedString(name)
  })

  // 返回表达式的字符串表示形式
  override def toString: String = toPrettySQL(expr)

  override def equals(that: Any): Boolean = that match {
    case that: Column => that.expr.equals(this.expr)
    case _ => false
  }

  override def hashCode: Int = this.expr.hashCode()

  /** 根据给定的表达式创建一个列。 */
  private def withExpr(newExpr: Expression): Column = new Column(newExpr)

  /**
   * 返回此列的表达式,具有现有名称或自动分配的名称。
   */
  private[sql] def named: NamedExpression = expr match {
    // 使用UnresolvedAlias包装UnresolvedAttribute,因为在解析UnresolvedAttribute时,我们将删除中间的Alias以进行ExtractValue链,并且我们需要再次对其进行别名以使其成为NamedExpression。
    case u: UnresolvedAttribute => UnresolvedAlias(u)

    case u: UnresolvedExtractValue => UnresolvedAlias(u)

    case expr: NamedExpression => expr

    // 留下未别名的生成器和空名称列表,因为在解析嵌套表达式类型后,分析器将生成正确的默认值。
    case g: Generator => MultiAlias(g, Nil)

    case func: UnresolvedFunction => UnresolvedAlias(func, Some(Column.generateAlias))

    // 如果有顶级的Cast,有机会给它一个更好的别名,如果在此Cast下有NamedExpression。
    case c: Cast =>
      c.transformUp {
        case c @ Cast(_: NamedExpression, _, _) => UnresolvedAlias(c)
      } match {
        case ne: NamedExpression => ne
        case _ => Alias(expr, toPrettySQL(expr))()
      }

    case a: AggregateExpression if a.aggregateFunction.isInstanceOf[TypedAggregateExpression] =>
      UnresolvedAlias(a, Some(Column.generateAlias))

    // 等到结构体被解析。这将生成一个更漂亮的别名。
    case struct: CreateNamedStructLike => UnresolvedAlias(struct)

    case expr: Expression => Alias(expr, toPrettySQL(expr))()
  }

  /**
   * 提供关于此列预期返回值的类型提示。此信息可用于在[[Dataset]]上执行`select`等操作,以自动将结果转换为正确的JVM类型。
   * @since 1.6.0
   */
  def as[U : Encoder]: TypedColumn[Any, U] = new TypedColumn[Any, U](expr, encoderFor[U])

  /**
   * 从复杂类型中提取一个值或多个值。
   * 支持以下类型的提取:
   * <ul>
   * <li>对于Array,可以使用整数序数来检索单个值。</li>
   * <li>对于Map,可以使用正确类型的键来检索单个值。</li>
   * <li>对于Struct,可以使用字符串字段名来提取该字段。</li>
   * <li>对于Array of Structs,可以使用字符串字段名来提取该数组中每个struct的字段,并返回一个字段的数组。</li>
   * </ul>
   * @group expr_ops
   * @since 1.4.0
   */
  def apply(extraction: Any): Column = withExpr {
    UnresolvedExtractValue(expr, lit(extraction).expr)
  }

  /**
   * 一元负号操作符,即取反表达式。
   * {{{
   *   // Scala:选择amount列并对所有值取反。
   *   df.select( -df("amount") )
   *
   *   // Java:
   *   import static org.apache.spark.sql.functions.*;
   *   df.select( negate(col("amount") );
   * }}}
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def unary_- : Column = withExpr { UnaryMinus(expr) }

  /**
   * 取反布尔表达式,即NOT。
   * {{{
   *   // Scala:选择非活动的行(isActive === false)
   *   df.filter( !df("isActive") )
   *
   *   // Java:
   *   import static org.apache.spark.sql.functions.*;
   *   df.filter( not(df.col("isActive")) );
   * }}}
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def unary_! : Column = withExpr { Not(expr) }

  /**
   * 相等性测试。
   * {{{
   *   // Scala:
   *   df.filter( df("colA") === df("colB") )
   *
   *   // Java
   *   import static org.apache.spark.sql.functions.*;
   *   df.filter( col("colA").equalTo(col("colB")) );
   * }}}
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def === (other: Any): Column = withExpr {
    val right = lit(other).expr
    if (this.expr == right) {
      logWarning(
        s"Constructing trivially true equals predicate, '${this.expr} = $right'. " +
          "Perhaps you need to use aliases.")
    }
    EqualTo(expr, right)
  }

  /**
   * 相等性测试。
   * {{{
   *   // Scala:
   *   df.filter( df("colA") === df("colB") )
   *
   *   // Java
   *   import static org.apache.spark.sql.functions.*;
   *   df.filter( col("colA").equalTo(col("colB")) );
   * }}}
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def equalTo(other: Any): Column = this === other

  /**
   * 不等性测试。
   * {{{
   *   // Scala:
   *   df.select( df("colA") =!= df("colB") )
   *   df.select( !(df("colA") === df("colB")) )
   *
   *   // Java:
   *   import static org.apache.spark.sql.functions.*;
   *   df.filter( col("colA").notEqual(col("colB")) );
   * }}}
   *
   * @group expr_ops
   * @since 2.0.0
    */
  def =!= (other: Any): Column = withExpr{ Not(EqualTo(expr, lit(other).expr)) }

  /**
   * 不等性测试。
   * {{{
   *   // Scala:
   *   df.select( df("colA") !== df("colB") )
   *   df.select( !(df("colA") === df("colB")) )
   *
   *   // Java:
   *   import static org.apache.spark.sql.functions.*;
   *   df.filter( col("colA").notEqual(col("colB")) );
   * }}}
   *
   * @group expr_ops
   * @since 1.3.0
    */
  @deprecated("!== does not have the same precedence as ===, use =!= instead", "2.0.0")
  def !== (other: Any): Column = this =!= other

  /**
   * 不等性测试。
   * {{{
   *   // Scala:
   *   df.select( df("colA") !== df("colB") )
   *   df.select( !(df("colA") === df("colB")) )
   *
   *   // Java:
   *   import static org.apache.spark.sql.functions.*;
   *   df.filter( col("colA").notEqual(col("colB")) );
   * }}}
   *
   * @group java_expr_ops
   * @since 1.3.0
   */
  def notEqual(other: Any): Column = withExpr { Not(EqualTo(expr, lit(other).expr)) }

  /**
   * 大于。
   * {{{
   *   // Scala:选择年龄大于21的人。
   *   people.select( people("age") > 21 )
   *
   *   // Java:
   *   import static org.apache.spark.sql.functions.*;
   *   people.select( people.col("age").gt(21) );
   * }}}
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def > (other: Any): Column = withExpr { GreaterThan(expr, lit(other).expr) }

  /**
   * 大于。
   * {{{
   *   // Scala:选择年龄大于21的人。
   *   people.select( people("age") > lit(21) )
   *
   *   // Java:
   *   import static org.apache.spark.sql.functions.*;
   *   people.select( people.col("age").gt(21) );
   * }}}
   *
   * @group java_expr_ops
   * @since 1.3.0
   */
  def gt(other: Any): Column = this > other
}
 
  /**
   * 小于运算符。
   * {{{
   *   // Scala: 以下选择小于21岁的人。
   *   people.select( people("age") < 21 )
   *
   *   // Java:
   *   people.select( people.col("age").lt(21) );
   * }}}
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def < (other: Any): Column = withExpr { LessThan(expr, lit(other).expr) }

  /**
   * 小于运算符。
   * {{{
   *   // Scala: 以下选择小于21岁的人。
   *   people.select( people("age") < 21 )
   *
   *   // Java:
   *   people.select( people.col("age").lt(21) );
   * }}}
   *
   * @group java_expr_ops
   * @since 1.3.0
   */
  def lt(other: Any): Column = this < other

  /**
   * 小于等于运算符。
   * {{{
   *   // Scala: 以下选择年龄为21或小于21岁的人。
   *   people.select( people("age") <= 21 )
   *
   *   // Java:
   *   people.select( people.col("age").leq(21) );
   * }}}
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def <= (other: Any): Column = withExpr { LessThanOrEqual(expr, lit(other).expr) }

  /**
   * 小于等于运算符。
   * {{{
   *   // Scala: 以下选择年龄为21或小于21岁的人。
   *   people.select( people("age") <= 21 )
   *
   *   // Java:
   *   people.select( people.col("age").leq(21) );
   * }}}
   *
   * @group java_expr_ops
   * @since 1.3.0
   */
  def leq(other: Any): Column = this <= other

  /**
   * 大于等于运算符。
   * {{{
   *   // Scala: 以下选择年龄为21或大于21岁的人。
   *   people.select( people("age") >= 21 )
   *
   *   // Java:
   *   people.select( people.col("age").geq(21) )
   * }}}
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def >= (other: Any): Column = withExpr { GreaterThanOrEqual(expr, lit(other).expr) }

  /**
   * 大于等于运算符。
   * {{{
   *   // Scala: 以下选择年龄为21或大于21岁的人。
   *   people.select( people("age") >= 21 )
   *
   *   // Java:
   *   people.select( people.col("age").geq(21) )
   * }}}
   *
   * @group java_expr_ops
   * @since 1.3.0
   */
  def geq(other: Any): Column = this >= other

  /**
   * 安全的相等性测试,对空值也有效。
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def <=> (other: Any): Column = withExpr {
    val right = lit(other).expr
    if (this.expr == right) {
      logWarning(
        s"构造了一个无意义的相等谓词,'${this.expr} <=> $right'。" +
          "也许你需要使用别名。")
    }
    EqualNullSafe(expr, right)
  }

  /**
   * 安全的相等性测试,对空值也有效。
   *
   * @group java_expr_ops
   * @since 1.3.0
   */
  def eqNullSafe(other: Any): Column = this <=> other

  /**
   * 根据条件选择不同的结果表达式。
   *
   * {{{
   *   // 示例:将性别字符串编码为整数。
   *
   *   // Scala:
   *   people.select(when(people("gender") === "male", 0)
   *     .when(people("gender") === "female", 1)
   *     .otherwise(2))
   *
   *   // Java:
   *   people.select(when(col("gender").equalTo("male"), 0)
   *     .when(col("gender").equalTo("female"), 1)
   *     .otherwise(2))
   * }}}
   *
   * @group expr_ops
   * @since 1.4.0
   */
  def when(condition: Column, value: Any): Column = this.expr match {
    case CaseWhen(branches, None) =>
      withExpr { CaseWhen(branches :+ ((condition.expr, lit(value).expr))) }
    case CaseWhen(branches, Some(_)) =>
      throw new IllegalArgumentException(
        "当once()应用后,不能再应用when()")
    case _ =>
      throw new IllegalArgumentException(
        "when()只能应用于之前由when()函数生成的Column对象")
  }

  /**
   * 根据条件选择不同的结果表达式。
   *
   * {{{
   *   // 示例:将性别字符串编码为整数。
   *
   *   // Scala:
   *   people.select(when(people("gender") === "male", 0)
   *     .when(people("gender") === "female", 1)
   *     .otherwise(2))
   *
   *   // Java:
   *   people.select(when(col("gender").equalTo("male"), 0)
   *     .when(col("gender").equalTo("female"), 1)
   *     .otherwise(2))
   * }}}
   *
   * @group expr_ops
   * @since 1.4.0
   */
  def otherwise(value: Any): Column = this.expr match {
    case CaseWhen(branches, None) =>
      withExpr { CaseWhen(branches, Option(lit(value).expr)) }
    case CaseWhen(branches, Some(_)) =>
      throw new IllegalArgumentException(
        "otherwise()只能应用于之前由when()函数生成的Column对象")
    case _ =>
      throw new IllegalArgumentException(
        "otherwise()只能应用于之前由when()函数生成的Column对象")
  }

  /**
   * 判断当前列是否在给定的上下界之间。
   *
   * @group java_expr_ops
   * @since 1.4.0
   */
  def between(lowerBound: Any, upperBound: Any): Column = {
    (this >= lowerBound) && (this <= upperBound)
  }

  /**
   * 判断当前表达式是否为NaN。
   *
   * @group expr_ops
   * @since 1.5.0
   */
  def isNaN: Column = withExpr { IsNaN(expr) }

  /**
   * 判断当前表达式是否为null。
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def isNull: Column = withExpr { IsNull(expr) }

  /**
   * 判断当前表达式是否不为null。
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def isNotNull: Column = withExpr { IsNotNull(expr) }

  /**
   * 逻辑或运算符。
   * {{{
   *   // Scala: 以下选择在学校或就业的人。
   *   people.filter( people("inSchool") || people("isEmployed") )
   *
   *   // Java:
   *   people.filter( people.col("inSchool").or(people.col("isEmployed")) );
   * }}}
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def || (other: Any): Column = withExpr { Or(expr, lit(other).expr) }

  /**
   * 逻辑或运算符。
   * {{{
   *   // Scala: 以下选择在学校或就业的人。
   *   people.filter( people("inSchool") || people("isEmployed") )
   *
   *   // Java:
   *   people.filter( people.col("inSchool").or(people.col("isEmployed")) );
   * }}}
   *
   * @group java_expr_ops
   * @since 1.3.0
   */
  def or(other: Column): Column = this || other

  /**
   * 逻辑与运算符。
   * {{{
   *   // Scala: 以下选择同时在学校和就业的人。
   *   people.select( people("inSchool") && people("isEmployed") )
   *
   *   // Java:
   *   people.select( people.col("inSchool").and(people.col("isEmployed")) );
   * }}}
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def && (other: Any): Column = withExpr { And(expr, lit(other).expr) }

  /**
   * 逻辑与运算符。
   * {{{
   *   // Scala: 以下选择同时在学校和就业的人。
   *   people.select( people("inSchool") && people("isEmployed") )
   *
   *   // Java:
   *   people.select( people.col("inSchool").and(people.col("isEmployed")) );
   * }}}
   *
   * @group java_expr_ops
   * @since 1.3.0
   */
  def and(other: Column): Column = this && other

  /**
   * 两个表达式的求和。
   * {{{
   *   // Scala: 以下选择一个人身高和体重的总和。
   *   people.select( people("height") + people("weight") )
   *
   *   // Java:
   *   people.select( people.col("height").plus(people.col("weight")) );
   * }}}
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def + (other: Any): Column = withExpr { Add(expr, lit(other).expr) }

  /**
   * 两个表达式的求和。
   * {{{
   *   // Scala: 以下选择一个人身高和体重的总和。
   *   people.select( people("height") + people("weight") )
   *
   *   // Java:
   *   people.select( people.col("height").plus(people.col("weight")) );
   * }}}
   *
   * @group java_expr_ops
   * @since 1.3.0
   */
  def plus(other: Any): Column = this + other

  /**
   * 减法运算符。从当前表达式中减去另一个表达式。
   * {{{
   *   // Scala: 以下选择人的身高与体重之差。
   *   people.select( people("height") - people("weight") )
   *
   *   // Java:
   *   people.select( people.col("height").minus(people.col("weight")) );
   * }}}
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def - (other: Any): Column = withExpr { Subtract(expr, lit(other).expr) }

  /**
   * 减法运算符。从当前表达式中减去另一个表达式。
   * {{{
   *   // Scala: 以下选择人的身高与体重之差。
   *   people.select( people("height") - people("weight") )
   *
   *   // Java:
   *   people.select( people.col("height").minus(people.col("weight")) );
   * }}}
   *
   * @group java_expr_ops
   * @since 1.3.0
   */
  def minus(other: Any): Column = this - other

  /**
   * 两个表达式的乘积。
   * {{{
   *   // Scala: 以下选择一个人身高与体重的乘积。
   *   people.select( people("height") * people("weight") )
   *
   *   // Java:
   *   people.select( people.col("height").multiply(people.col("weight")) );
   * }}}
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def * (other: Any): Column = withExpr { Multiply(expr, lit(other).expr) }

  /**
   * 两个表达式的乘积。
   * {{{
   *   // Scala: 以下选择一个人身高与体重的乘积。
   *   people.select( people("height") * people("weight") )
   *
   *   // Java:
   *   people.select( people.col("height").multiply(people.col("weight")) );
   * }}}
   *
   * @group java_expr_ops
   * @since 1.3.0
   */
  def multiply(other: Any): Column = this * other

  /**
   * 除法运算符。将当前表达式除以另一个表达式。
   * {{{
   *   // Scala: 以下选择一个人身高除以体重。
   *   people.select( people("height") / people("weight") )
   *
   *   // Java:
   *   people.select( people.col("height").divide(people.col("weight")) );
   * }}}
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def / (other: Any): Column = withExpr { Divide(expr, lit(other).expr) }

  /**
   * 除法运算符。将当前表达式除以另一个表达式。
   * {{{
   *   // Scala: 以下选择一个人身高除以体重。
   *   people.select( people("height") / people("weight") )
   *
   *   // Java:
   *   people.select( people.col("height").divide(people.col("weight")) );
   * }}}
   *
   * @group java_expr_ops
   * @since 1.3.0
   */
  def divide(other: Any): Column = this / other

  /**
   * 取模运算符(即求余数)。
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def % (other: Any): Column = withExpr { Remainder(expr, lit(other).expr) }

  /**
   * 取模运算符(即求余数)。
   *
   * @group java_expr_ops
   * @since 1.3.0
   */
  def mod(other: Any): Column = this % other

  /**
   * 判断当前表达式的值是否在给定列表中。
   *
   * 注意:由于列表中元素的类型在运行时才能确定,因此元素将被“向上转型”为最常见的类型进行比较。
   * 例如:
   *   1)对于“Int vs String”情况,将“Int”向上转型为“String”,比较结果为“String vs String”。
   *   2)对于“Float vs Double”情况,将“Float”向上转型为“Double”,比较结果为“Double vs Double”。
   *
   * @group expr_ops
   * @since 1.5.0
   */
  @scala.annotation.varargs
  def isin(list: Any*): Column = withExpr { In(expr, list.map(lit(_).expr)) }

  /**
   * 判断当前表达式的值是否包含在提供的集合中。
   *
   * 注意:由于集合中元素的类型在运行时才能确定,因此元素将被“向上转型”为最常见的类型进行比较。
   * 例如:
   *   1)对于“Int vs String”情况,将“Int”向上转型为“String”,比较结果为“String vs String”。
   *   2)对于“Float vs Double”情况,将“Float”向上转型为“Double”,比较结果为“Double vs Double”。
   *
   * @group expr_ops
   * @since 2.4.0
   */
  def isInCollection(values: scala.collection.Iterable[_]): Column = isin(values.toSeq: _*)

  /**
   * 判断当前表达式的值是否包含在提供的集合中。
   *
   * 注意:由于集合中元素的类型在运行时才能确定,因此元素将被“向上转型”为最常见的类型进行比较。
   * 例如:
   *   1)对于“Int vs String”情况,将“Int”向上转型为“String”,比较结果为“String vs String”。
   *   2)对于“Float vs Double”情况,将“Float”向上转型为“Double”,比较结果为“Double vs Double”。
   *
   * @group java_expr_ops
   * @since 2.4.0
   */
  def isInCollection(values: java.lang.Iterable[_]): Column = isInCollection(values.asScala)

  /**
   * SQL的LIKE表达式。基于SQL LIKE匹配返回一个布尔列。
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def like(literal: String): Column = withExpr { Like(expr, lit(literal).expr) }

  /**
   * SQL的RLIKE表达式(带有正则表达式的LIKE)。基于正则表达式匹配返回一个布尔列。
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def rlike(literal: String): Column = withExpr { RLike(expr, lit(literal).expr) }

  /**
   * 从数组中获取指定位置的元素,或者从MapType中根据键获取值的表达式。
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def getItem(key: Any): Column = withExpr { UnresolvedExtractValue(expr, Literal(key)) }

  /**
   * 从StructType中根据字段名获取字段的表达式。
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def getField(fieldName: String): Column = withExpr {
    UnresolvedExtractValue(expr, Literal(fieldName))
  }

  /**
   * 返回子字符串的表达式。
   * @param startPos 表示起始位置的表达式。
   * @param len 表示子字符串长度的表达式。
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def substr(startPos: Column, len: Column): Column = withExpr {
    Substring(expr, startPos.expr, len.expr)
  }

  /**
   * 返回子字符串的表达式。
   * @param startPos 起始位置。
   * @param len 子字符串长度。
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def substr(startPos: Int, len: Int): Column = withExpr {
    Substring(expr, lit(startPos).expr, lit(len).expr)
  }

  /**
   * 判断当前表达式的值是否包含另一个元素。返回一个布尔列,基于字符串匹配。
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def contains(other: Any): Column = withExpr { Contains(expr, lit(other).expr) }

  /**
   * 判断字符串是否以指定的列开始。返回一个布尔列,基于字符串匹配。
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def startsWith(other: Column): Column = withExpr { StartsWith(expr, lit(other).expr) }

  /**
   * 判断字符串是否以指定的字符串字面量开始。返回一个布尔列,基于字符串匹配。
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def startsWith(literal: String): Column = this.startsWith(lit(literal))

  /**
   * 判断字符串是否以指定的列结束。返回一个布尔列,基于字符串匹配。
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def endsWith(other: Column): Column = withExpr { EndsWith(expr, lit(other).expr) }

  /**
   * 判断字符串是否以指定的字符串字面量结束。返回一个布尔列,基于字符串匹配。
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def endsWith(literal: String): Column = this.endsWith(lit(literal))

  /**
   * 为列指定别名。与`as`方法相同。
   * {{{
   *   // 将colA重命名为colB。
   *   df.select($"colA".alias("colB"))
   * }}}
   *
   * @group expr_ops
   * @since 1.4.0
   */
  def alias(alias: String): Column = name(alias)

  /**
   * 为列指定别名。
   * {{{
   *   // 将colA重命名为colB。
   *   df.select($"colA".as("colB"))
   * }}}
   *
   * 如果当前列具有元数据关联,则此元数据将传播到新列。如果不需要此功能,请使用具有显式空元数据的`as`方法。
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def as(alias: String): Column = name(alias)

  /**
   * (仅Scala)为表生成函数的结果分配给定的别名。
   * {{{
   *   // 将colA重命名为colB。
   *   df.select(explode($"myMap").as("key" :: "value" :: Nil))
   * }}}
   *
   * @group expr_ops
   * @since 1.4.0
   */
  def as(aliases: Seq[String]): Column = withExpr { MultiAlias(expr, aliases) }

  /**
   * 为表生成函数的结果分配给定的别名。
   * {{{
   *   // 将colA重命名为colB。
   *   df.select(explode($"myMap").as("key" :: "value" :: Nil))
   * }}}
   *
   * @group expr_ops
   * @since 1.4.0
   */
  def as(aliases: Array[String]): Column = withExpr { MultiAlias(expr, aliases) }

  /**
   * 为列指定别名。
   * {{{
   *   // 将colA重命名为colB。
   *   df.select($"colA".as('colB))
   * }}}
   *
   * 如果当前列具有元数据关联,则此元数据将传播到新列。如果不需要此功能,请使用具有显式空元数据的`as`方法。
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def as(alias: Symbol): Column = name(alias.name)

  /**
   * 为列指定带有元数据的别名。
   * {{{
   *   val metadata: Metadata = ...
   *   df.select($"colA".as("colB", metadata))
   * }}}
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def as(alias: String, metadata: Metadata): Column = withExpr {
    Alias(expr, alias)(explicitMetadata = Some(metadata))
  }

  /**
   * 给列一个名称(别名)。
   * {{{
   *   // 将colA重命名为colB。
   *   df.select($"colA".name("colB"))
   * }}}
   *
   * 如果当前列具有元数据关联,则此元数据将传播到新列。如果不需要此功能,请使用具有显式空元数据的`as`方法。
   *
   * @group expr_ops
   * @since 2.0.0
   */
  def name(alias: String): Column = withExpr {
    expr match {
      case ne: NamedExpression => Alias(expr, alias)(explicitMetadata = Some(ne.metadata))
      case other => Alias(other, alias)()
    }
  }

  /**
   * 将列转换为不同的数据类型。
   * {{{
   *   // 将colA转换为IntegerType。
   *   import org.apache.spark.sql.types.IntegerType
   *   df.select(df("colA").cast(IntegerType))
   *
   *   // 等价于
   *   df.select(df("colA").cast("int"))
   * }}}
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def cast(to: DataType): Column = withExpr { Cast(expr, to) }

  /**
   * 将列转换为不同的数据类型,使用类型的规范字符串表示。
   * 支持的类型有:"string"、"boolean"、"byte"、"short"、"int"、"long"、"float"、"double"、"decimal"、"date"、"timestamp"。
   * {{{
   *   // 将colA转换为整数。
   *   df.select(df("colA").cast("int"))
   * }}}
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def cast(to: String): Column = cast(CatalystSqlParser.parseDataType(to))

  /**
   * 返回一个基于列的降序排序表达式。
   * {{{
   *   // Scala
   *   df.sort(df("age").desc)
   *
   *   // Java
   *   df.sort(df.col("age").desc());
   * }}}
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def desc: Column = withExpr { SortOrder(expr, Descending) }

  /**
   * 返回一个基于列的降序排序表达式,并且null值出现在非null值之前。
   * {{{
   *   // Scala:按照age列降序排序,并且null值出现在最前面。
   *   df.sort(df("age").desc_nulls_first)
   *
   *   // Java
   *   df.sort(df.col("age").desc_nulls_first());
   * }}}
   *
   * @group expr_ops
   * @since 2.1.0
   */
  def desc_nulls_first: Column = withExpr { SortOrder(expr, Descending, NullsFirst, Set.empty) }

  /**
   * 返回一个基于列的降序排序表达式,并且null值出现在非null值之后。
   * {{{
   *   // Scala:按照age列降序排序,并且null值出现在最后面。
   *   df.sort(df("age").desc_nulls_last)
   *
   *   // Java
   *   df.sort(df.col("age").desc_nulls_last());
   * }}}
   *
   * @group expr_ops
   * @since 2.1.0
   */
  def desc_nulls_last: Column = withExpr { SortOrder(expr, Descending, NullsLast, Set.empty) }

  /**
   * 返回一个基于列的升序排序表达式。
   * {{{
   *   // Scala:按照age列升序排序。
   *   df.sort(df("age").asc)
   *
   *   // Java
   *   df.sort(df.col("age").asc());
   * }}}
   *
   * @group expr_ops
   * @since 1.3.0
   */
  def asc: Column = withExpr { SortOrder(expr, Ascending) }

  /**
   * 返回一个基于列的升序排序表达式,并且null值出现在非null值之前。
   * {{{
   *   // Scala:按照age列升序排序,并且null值出现在最前面。
   *   df.sort(df("age").asc_nulls_first)
   *
   *   // Java
   *   df.sort(df.col("age").asc_nulls_first());
   * }}}
   *
   * @group expr_ops
   * @since 2.1.0
   */
  def asc_nulls_first: Column = withExpr { SortOrder(expr, Ascending, NullsFirst, Set.empty) }

  /**
   * 返回一个基于列的升序排序表达式,并且null值出现在非null值之后。
   * {{{
   *   // Scala:按照age列升序排序,并且null值出现在最后面。
   *   df.sort(df("age").asc_nulls_last)
   *
   *   // Java
   *   df.sort(df.col("age").asc_nulls_last());
   * }}}
   *
   * @group expr_ops
   * @since 2.1.0
   */
  def asc_nulls_last: Column = withExpr { SortOrder(expr, Ascending, NullsLast, Set.empty) }

  /**
   * 将表达式打印到控制台以进行调试。
   *
   * @group df_ops
   * @since 1.3.0
   */
  def explain(extended: Boolean): Unit = {
    // scalastyle:off println
    if (extended) {
      println(expr)
    } else {
      println(expr.sql)
    }
    // scalastyle:on println
  }

  /**
   * 计算当前表达式与另一个表达式的按位或。
   * {{{
   *   df.select($"colA".bitwiseOR($"colB"))
   * }}}
   *
   * @group expr_ops
   * @since 1.4.0
   */
  def bitwiseOR(other: Any): Column = withExpr { BitwiseOr(expr, lit(other).expr) }

  /**
   * 计算当前表达式与另一个表达式的按位与。
   * {{{
   *   df.select($"colA".bitwiseAND($"colB"))
   * }}}
   *
   * @group expr_ops
   * @since 1.4.0
   */
  def bitwiseAND(other: Any): Column = withExpr { BitwiseAnd(expr, lit(other).expr) }

  /**
   * 计算当前表达式与另一个表达式的按位异或。
   * {{{
   *   df.select($"colA".bitwiseXOR($"colB"))
   * }}}
   *
   * @group expr_ops
   * @since 1.4.0
   */
  def bitwiseXOR(other: Any): Column = withExpr { BitwiseXor(expr, lit(other).expr) }

  /**
   * 定义一个窗口列。
   *
   * {{{
   *   val w = Window.partitionBy("name").orderBy("id")
   *   df.select(
   *     sum("price").over(w.rangeBetween(Window.unboundedPreceding, 2)),
   *     avg("price").over(w.rowsBetween(Window.currentRow, 4))
   *   )
   * }}}
   *
   * @group expr_ops
   * @since 1.4.0
   */
  def over(window: expressions.WindowSpec): Column = window.withAggregate(this)

  /**
   * 定义一个空的分析子句。在这种情况下,分析函数将应用并呈现给结果集中的所有行。
   *
   * {{{
   *   df.select(
   *     sum("price").over(),
   *     avg("price").over()
   *   )
   * }}}
   *
   * @group expr_ops
   * @since 2.0.0
   */
  def over(): Column = over(Window.spec)

}
 
/**
 * 用于构建模式的方便类。
 *
 * @since 1.3.0
 */
@InterfaceStability.Stable
class ColumnName(name: String) extends Column(name) {

  /**
   * 创建一个新的布尔类型的`StructField`。
   * @since 1.3.0
   */
  def boolean: StructField = StructField(name, BooleanType)

  /**
   * 创建一个新的字节类型的`StructField`。
   * @since 1.3.0
   */
  def byte: StructField = StructField(name, ByteType)

  /**
   * 创建一个新的短整型类型的`StructField`。
   * @since 1.3.0
   */
  def short: StructField = StructField(name, ShortType)

  /**
   * 创建一个新的整型类型的`StructField`。
   * @since 1.3.0
   */
  def int: StructField = StructField(name, IntegerType)

  /**
   * 创建一个新的长整型类型的`StructField`。
   * @since 1.3.0
   */
  def long: StructField = StructField(name, LongType)

  /**
   * 创建一个新的单精度浮点型类型的`StructField`。
   * @since 1.3.0
   */
  def float: StructField = StructField(name, FloatType)

  /**
   * 创建一个新的双精度浮点型类型的`StructField`。
   * @since 1.3.0
   */
  def double: StructField = StructField(name, DoubleType)

  /**
   * 创建一个新的字符串类型的`StructField`。
   * @since 1.3.0
   */
  def string: StructField = StructField(name, StringType)

  /**
   * 创建一个新的日期类型的`StructField`。
   * @since 1.3.0
   */
  def date: StructField = StructField(name, DateType)

  /**
   * 创建一个新的十进制类型的`StructField`。
   * @since 1.3.0
   */
  def decimal: StructField = StructField(name, DecimalType.USER_DEFAULT)

  /**
   * 创建一个新的指定精度和小数位数的十进制类型的`StructField`。
   * @since 1.3.0
   */
  def decimal(precision: Int, scale: Int): StructField =
    StructField(name, DecimalType(precision, scale))

  /**
   * 创建一个新的时间戳类型的`StructField`。
   * @since 1.3.0
   */
  def timestamp: StructField = StructField(name, TimestampType)

  /**
   * 创建一个新的二进制类型的`StructField`。
   * @since 1.3.0
   */
  def binary: StructField = StructField(name, BinaryType)

  /**
   * 创建一个新的数组类型的`StructField`。
   * @since 1.3.0
   */
  def array(dataType: DataType): StructField = StructField(name, ArrayType(dataType))

  /**
   * 创建一个新的映射类型的`StructField`。
   * @since 1.3.0
   */
  def map(keyType: DataType, valueType: DataType): StructField =
    map(MapType(keyType, valueType))

  def map(mapType: MapType): StructField = StructField(name, mapType)

  /**
   * 创建一个新的结构体类型的`StructField`。
   * @since 1.3.0
   */
  def struct(fields: StructField*): StructField = struct(StructType(fields))

  /**
   * 创建一个新的指定结构体类型的`StructField`。
   * @since 1.3.0
   */
  def struct(structType: StructType): StructField = StructField(name, structType)
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BigDataMLApplication

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值