重置窗口函数的计数器

Posted

技术标签:

【中文标题】重置窗口函数的计数器【英文标题】:Reset counter on window functions 【发布时间】:2020-04-24 14:33:34 【问题描述】:

我有一个如下所示的数据集,我想创建一个新的 C 列,它就像一个计数器/行号,每次 B 列的 0 被 A 的列值分区时都应该重置它

仅使用 SparkSQL / SQL(我可以使用 Pyspark 完成)

>>> rdd = sc.parallelize([
...     [1, 0], [1, 1],[1, 1], [1, 0], [1, 1],
...     [1, 1], [2, 1], [2, 1], [3, 0], [3, 1], [3, 1], [3, 1]])
>>> df = rdd.toDF(['A', 'B'])
>>> 
>>> df.show()
+---+---+
|  A|  B|
+---+---+
|  1|  0|
|  1|  1|
|  1|  1|
|  1|  0|
|  1|  1|
|  1|  1|
|  2|  1|
|  2|  1|
|  3|  0|
|  3|  1|
|  3|  1|
|  3|  1|
+---+---+

我想要达到的目标

+---+---+---+
|  A|  B|  C|
+---+---+---+
|  1|  0|  1|
|  1|  1|  2|
|  1|  1|  3|
|  1|  0|  1|
|  1|  1|  2|
|  1|  1|  3|
|  2|  1|  1|
|  2|  1|  2|
|  3|  0|  1|
|  3|  1|  2|
|  3|  1|  3|
|  3|  1|  4|
+---+---+---+

我目前拥有的东西

>>> spark.sql('''
...    select *, row_number() over(partition by A order by A) as C from df
...    ''').show()

    +---+---+---+
    |  A|  B|  C|
    +---+---+---+
    |  1|  0|  1|
    |  1|  1|  2|
    |  1|  1|  3|
    |  1|  0|  4|
    |  1|  1|  5|
    |  1|  1|  6|
    |  3|  0|  1|
    |  3|  1|  2|
    |  3|  1|  3|
    |  3|  1|  4|
    |  2|  1|  1|
    |  2|  1|  2|
    +---+---+---+

【问题讨论】:

您需要一个指定数据顺序的列。 那将是 A 列 【参考方案1】:

SQL 表代表无序 集合。您需要一个指定数据顺序的列。

使用这样的列,您可以累积 0 值,因为它们似乎是中断。所以:

select df.*, row_number() over (partition by A, grp order by A) as C
from (select df.*,
             sum(case when b = 0 then 1 else 0 end) over (partition by A order by <ordering column>) as grp
      from df
      ) df

【讨论】:

哇。您能否说明一下这个分组是如何工作的! @Bala 。 . .它正在对具有0 计数的行进行累积总和。这定义了您想要的row_number() 分组。您可以运行子查询来查看中间结果。

以上是关于重置窗口函数的计数器的主要内容,如果未能解决你的问题,请参考以下文章

计数窗口函数 MySQL 中每个分区的最大计数

使用窗口函数计算滚动计数

如何在 Postgresql 的窗口函数中“区分”计数?

如何使用计数窗口函数获取百分比?

pandas使用rolling函数计算dataframe指定数据列特定窗口下的滚动有效数值计数(rolling count)自定义指定滚动窗口的大小(window size)

使用窗口函数确定 PostgreSQL 中的 30 天运行计数