pyspark 在日历表中标记前3个和后2个工作日

a11xaf1n  于 5个月前  发布在  Spark
关注(0)|答案(2)|浏览(58)

在我的数据库中有一个辅助表,它包含一年中的所有日子,其中有一列(is_working_day),它是一个布尔标志,指示这一天是否是工作日。
我想在这个表上建立一个查询,它允许我按顺序标记一个月的最后2个工作日和前三个工作日(1,2,3,4,5)。
输出应该类似于:
| 天|是工作日|标志|
| --|--|--|
| 2023年01月01日| 0 | 0 |
| 2023年01月02日| 1 | 1 |
| 2023年01月03日| 1 | 2 |
| 2023年01月04日| 1 | 0 |
| 2023年01月05日| 1 | 0 |
| ......这是什么?|......这是什么?|......这是什么?|
| 2023年1月29日| 1 | 3 |
| 2023年1月30日| 1 | 4 |
| 2023年1月31日| 1 | 5 |
| 2023年02月01日星期一| 1 | 1 |
| 2023年02月02日| 1 | 2 |
Day和is_working day已经存在于我的表中,我想要的是一些逻辑来创建“flag”列。

yebdmbv4

yebdmbv41#

如果只使用SQL的解决方案是可以接受的,那么你可以使用窗口函数来生成标志列。一个例子:

with cte as (
    select *
         , sum(is_working_day) over (partition by datepart(year, day), datepart(month, day) order by day) as rn
         , sum(is_working_day) over (partition by datepart(year, day), datepart(month, day)) as mv
    from t
)
select day
     , is_working_day
     , case
           when is_working_day = 1 and rn >= 1 and rn <= 2 then rn
           when is_working_day = 1 and rn > mv - 3 then 5 - (mv - rn)
       end as flag
from cte

字符串
测试结果:
| 天|是工作日|标志|
| --|--|--|
| 2023-01-01 2023-01-01| 0 |* 空 |
| 2023-01-02 2023-01-02| 1 | 1 |
| 2023-01-03 2023-01-03| 0 |
|
| 2023-01-04 2023-01-04| 1 | 2 |
| 2023-01-05 2023-01-05| 1 | 3 |
| 2023-01-29 2023-01-29 2023-01-29| 1 | 4 |
| 2023-01-30 - 2023-01-30| 0 |
空 *|
| 2023-01-31 -01- 01 - 01 - 01| 1 | 5 |
| 2023-02-01 2023-02-01 2023-02-01| 1 | 1 |
| 2023-02-02 2023 -02-02| 1 | 2 |
将日期部分提取函数替换为RDBMS中可用的函数。
DB<>Fiddle

yk9xbfzb

yk9xbfzb2#

试试这个:

from pyspark.sql.functions import *
from pyspark.sql import Window
ab=ab.withColumn("Day",to_date(col("Day"),"dd-mm-yyyy"))
ab=ab.withColumn("Month",month(col("Day")))
w0=Window.partitionBy('month','is_working_day').orderBy('Day')
w1=Window.partitionBy('month','is_working_day')
ab=ab.withColumn("row",row_number().over(w0))


ab=ab.withColumn("flag",when((col("is_working_day")==1) & (col("row")==1),1)\
                       .when((col("is_working_day")==1) & (col("row")==2),2)\
                       .when((col("is_working_day")==1) & (col("row")==max(col("row")).over(w1)),5)\
                       .when((col("is_working_day")==1) & (col("row")==max(col("row")).over(w1)-1),4)\
                       .when((col("is_working_day")==1) & (col("row")==max(col("row")).over(w1)-2),3)\
                       .otherwise(0))

字符串

相关问题