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



我有一个带有"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,依此类推。

我希望我的DataFrame看起来像这样... :

+---------+----------+---------+
|  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 月 02 日日期最早,因此其数字为 1。 由于有 2 行具有相同的日期,因此 1 位于两次。 在 2018-01-02 之后,下一个日期是 2018-03-01,因此它的编号是 2,依此类推......如何创建这样的列?

这可以通过Window函数中的dense_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列。

注意:to_date(col("ds"),"yyyy-MM-dd")是强制性的,否则它将被视为字符串并且无法生存。

你应该创建一个函数来获取最旧的查询,没有这样的数字:

SELECT * FROM tablename WHERE number IS NULL ORDER BY ds ASC

然后进行另一个查询,获得最大的数字:

SELECT * FROM tablename ORDER BY number DESC

然后,如果两个查询具有相同的日期,则使用相同的数字更新表:

UPDATE tablename SET number = 'greatest number from first query' WHERE ds = 'the date from first query'

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

UPDATE tablename SET number= 'greatest number from first query' + 1 WHERE ds = 'the date from first query'

要完成这项工作,您应该首先将数字 1 断言到最旧的条目。 您应该在循环中执行此操作,直到第一个查询(检查是否有任何未设置的数字(为空。 第一个查询假设空列全部为 null,如果是另一种情况,则应更改 WHERE 条件以检查列何时为空。

最新更新