Postgres 使用 CTE 优先更新表

我是索曼

我有一个员工休假余额表如下

emp_code 离开类型 年月 平衡 优先
1 PL 202205 2 0
1 SL 202205 1 1
2 PL 202205 3 0
2 SL 202205 1 1
3 PL 202205 1 0
3 SL 202205 1 1

考勤表如下

emp_code 日期 年月 出勤率 离开
3 2022-05-01 202205 1
3 2022-05-02 202205 1
3 2022-05-03 202205 1
1 2022-05-01 202205 0
1 2022-05-02 202205 0
1 2022-05-03 202205 0
1 2022-05-04 202205 0
2 2022-05-01 202205 1
2 2022-05-02 202205 1

如果出勤字段值为 0 ,我只想更新attendance table相应的休假(基于优先级和可用性)

例如:员工 1 有 3 个假期余额和 4 天缺勤

更新后emp_code 1的出勤记录如下

emp_code 日期 年月 出勤率 离开
1 2022-05-01 202205 0 PL
1 2022-05-02 202205 0 PL
1 2022-05-03 202205 0 SL
1 2022-05-04 202205 0

我知道,我们可以通过 SP 或函数来做到这一点。但是我的公司政策不允许我创建 SP 或函数(我可以通过我的后端代码更新它,但是有数百万条记录需要更新,所以我担心性能)

我想知道,有没有办法在 PG 中使用 CTE/Window 函数/任何其他方式来实现这一点?

这是一个小提琴https://www.db-fiddle.com/f/4jyoMCicNSZpjMt4jFYoz5/4952

谢谢

迈克·奥内克

如果您的小提琴中的最后一条出勤记录有误并被删除,那么我的方法是:

  1. generate_series()使用并根据优先级分配行号将当月的休假余额扩展到行
  2. 为一个月内的缺​​勤分配行号
  3. 计算从缺勤到离开记录的左连接变化
with leave_rows as (
  select b.*, 
         row_number() over (partition by emp_code, yearmonth
                                order by priority) as use_order
    from emp_leave_balance b
         cross join lateral generate_series(1, b.balance, 1)
), absence_rows as (
  select a.*, 
         row_number() over (partition by emp_code, yearmonth
                                order by date) as use_order
    from attendance a
   where attendance = 0
), changes as (
  select a.emp_code, a.date, a.yearmonth, a.attendance, l.leave_type
  from absence_rows a
       left join leave_rows l
         on (l.emp_code, l.yearmonth, l.use_order) = 
               (a.emp_code, a.yearmonth, a.use_order)
)
update attendance 
   set leave = c.leave_type
  from changes c
 where (c.emp_code, c.date) = (attendance.emp_code, attendance.date)
;

你更新的小提琴

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章