Scala 如何将日期与计数或整数关联

Scala 如何将日期与计数或整数关联,scala,apache-spark,apache-spark-sql,Scala,Apache Spark,Apache Spark Sql,我有一个带有“id”和“date”列的DataFrame。日期的格式为yyyy mm dd以下是一个示例: +---------+----------+ | item_id| ds| +---------+----------+ | 25867869|2018-05-01| | 17190474|2018-01-02| | 19870756|2018-01-02| |172248680|2018-07-29| | 41148162|2018-03-01| +---------+-

我有一个带有“id”和“date”列的
DataFrame
。日期的格式为yyyy mm dd以下是一个示例:

+---------+----------+
|  item_id|        ds|
+---------+----------+
| 25867869|2018-05-01|
| 17190474|2018-01-02|
| 19870756|2018-01-02|
|172248680|2018-07-29|
| 41148162|2018-03-01|
+---------+----------+
我想创建一个新列,其中每个日期都与一个从1开始的整数相关联。这样最小的(最早的)日期得到整数1,下一个(最早的第二个日期)被分配到2,依此类推

我想让我的
数据帧
看起来像这样…:

+---------+----------+---------+
|  item_id|        ds|   number|
+---------+----------+---------+
| 25867869|2018-05-01|        3|
| 17190474|2018-01-02|        1|
| 19870756|2018-01-02|        1|
|172248680|2018-07-29|        4|
| 41148162|2018-03-01|        2|
+---------+----------+---------+
说明


2018年1月2日日期最早,因此其编号为1。由于有两行具有相同的日期,因此1被定位两次。2018-01-02之后的下一个日期为2018-03-01,因此其编号为2,以此类推。。。如何创建这样的列?

您应该创建一个函数来获取没有数字的最旧查询,例如:

从tablename中选择*其中数字为空,按ds ASC排序

然后在获得最大数量的位置进行另一个查询:

从tablename中选择*按数字顺序描述

然后,如果两个查询的日期相同,则使用相同的编号更新表:

更新tablename SET number='第一次查询的最大数',其中ds='第一次查询的日期'

或者,如果日期不同,则相同,但在数字上加1:

更新tablename SET number='第一次查询的最大数'+1,其中ds='第一次查询的日期'

要实现这一点,您应该首先将数字1关联到最早的条目。 您应该在循环中执行此操作,直到第一个查询(检查是否有未设置的数字)为空。
第一个查询显示空列全部为null,如果是另一种情况,则应更改WHERE条件以检查列何时为空。

这可以通过
窗口中的
稠密\u rank
函数实现

import org.apache.spark.sql.expressions.Window
import org.apache.spark.sql.functions._
val win = Window.orderBy(to_date(col("ds"),"yyyy-MM-dd").asc)
val df1 = df.withColumn("number", dense_rank() over win)
df1
将根据需要设置列
number


注意:
截止日期(col(“ds”),“yyyy-MM-dd”)
是必需的,否则它将被视为字符串,无法继续使用。

它的工作速度非常慢,因为我的数据是在ds上分区的。在运行代码时,它还会显示一条警告:“WARN WindowExec:没有为窗口操作定义分区!将所有数据移动到单个分区,这可能会导致严重的性能下降。”,您能帮我解决这个问题吗?因为您的要求是根据整个表数据中的日期增加整数的顺序,需要将整个数据视为单个分区。。。。。。。。如果你只需要唯一的数字(而不是连续的数字),有更快的选择。如果我们找到最早的日期并开始使用“date diff”功能找出日差,这不会产生任何问题,因为我的日期数据非常密集,几乎所有日期都包含在其中。你能帮我用scala编写我的想法吗?我觉得这很值得一试。即使您可能无法获得连续的数字,我希望它满足您的要求