暂无图片
请教一SQL(Oracle数据库)
我来答
分享
刘晓华
2024-05-08
请教一SQL(Oracle数据库)
暂无图片 100M

各位高手看看这个SQL怎么写?

背景是公司年假计算规则转换,每个人按旧规则计算出来有一条旧规则的剩余天数,时段为P1,后面的每个时段的应有天数(S_D)和该时段已休天数也很好算,问题是从第二个时段P2开始的期初数(R_D)怎么计算,从P2开始往后的R_D = 上一时段剩余天数(P_D)+本时段期初天数(S_D),但不能用lead或lag, 应该要用model, 这个带model的SQL怎么写?相当于计算出蓝色部分。假设已有数据来自试图V_leave, 谢谢


我来答
添加附件
收藏
分享
问题补充
3条回答
默认
最新
lianR

你可以使用Oracle的MODEL子句来实现这个需求。MODEL子句允许你使用一种类似于电子表格的方式来处理数据。以下是一个可能的解决方案:

```sql
SELECT  *
FROM  V_leave
MODEL
    PARTITION  BY  (员工)
    ORDER  BY  时段
    DIMENSION  BY  (ROW_NUMBER()  OVER  (PARTITION  BY  员工  ORDER  BY  时段)  rn)
    MEASURES  (时段,  应有天数  S_D,  已休天数,  剩余天数  P_D,  0  R_D)
    RULES  (
     R_D[ANY]  =  NVL(P_D[CV()-1],  0)  +  S_D[CV()]
    )
```

这个查询首先使用PARTITION  BY和ORDER  BY子句对数据进行排序和分组。然后,使用DIMENSION  BY子句创建一个新的维度rn,它是每个员工的时段的行号。MEASURES子句定义了模型的度量。

在RULES子句中,我们定义了一个规则来计算R_D。这个规则使用ANY关键字来表示它适用于所有行。规则的右边是一个表达式,它使用CV()函数来引用当前行的rn值。CV()-1表示前一行,所以P_D[CV()-1]是前一行的剩余天数。S_D[CV()]是当前行的应有天数。NVL函数用于处理第一行,因为它没有前一行。

这个查询的结果是一个新的表,它包含了原始的列,以及一个新的列R_D,它是根据你的规则计算出来的。

暂无图片 评论
暂无图片 有用 0
暂无图片
yBmZlQzJ

这题目我头都看晕了,P1 是什么?是字符串,那怎么参与计算?能不能写个完整的例子。

暂无图片 评论
暂无图片 有用 1
刘晓华
题主
2024-05-08
P1代表一个时段,有开始日期和结束日期,例如2023/05/01----2024/04/30
刘晓华
题主
2024-05-08
其实不需要关注P1是什么,关键每一行(从第二行开始)的期初数要动态的计算,Oracle里model字句可以做到,以前没用过,在看...
W
w83

写个开窗函数不就好了?

SELECT

EMID

,PERIOD

,LAG(P_D) OVER(PARTITION BY EMID ORDER BY PERIOD ASC) --  上一个时段的剩余天数

,R_D                                                                                              --  本时段的期初天数

FROM 表

暂无图片 评论
暂无图片 有用 0
刘晓华
题主
2024-05-08
这个需求不能用lag,lag是一开始每一样的数据已经确定了!但这个不同,好比仓库算库存,是动态的,要用model
刘晓华
题主
2024-05-16
这是一个lag无法完成的需求,lag是针对在每一样的值事先确定的情况,而这里的R_D值是动态计算的,如果用lag, 要加n个lag,例如lag(r_d,1) ...lag(r_d,2)...lag(r_d,3)...,行数很多的话,就无法算了,要加无数个decode判断!
回答交流
提交
问题信息
请登录之后查看
邀请回答
暂无人订阅该标签,敬请期待~~
暂无图片墨值悬赏