【发布时间】:2019-03-02 11:25:53
【问题描述】:
我需要解决的问题:
为了计算每天用于(公共)假期或病假的小时数,使用前 3 个月的平均工作时间(起始值为每天 8 小时)。
棘手的部分是需要考虑上个月的计算值,这意味着如果上个月有一个公共假期,分配了 8.5 小时的计算值,这些计算的小时数会影响平均值上个月每天的工作时间,然后用于分配给当前月份假期的工作时间。
到目前为止,我只提出了以下内容,还没有考虑到逐行计算:
WITH
const (h_target, h_extra) AS (VALUES (8.0, 20)),
monthly_sums (c_month, d_work, d_off, h_work) AS (VALUES
('2018-12', 16, 5, 150.25),
('2019-01', 20, 3, 171.25),
('2019-02', 15, 5, 120.5)
),
calc AS (
SELECT
ms.*,
(ms.d_work + ms.d_off) AS d_total,
(ms.h_work + ms.d_off * const.h_target) AS h_total,
(avg((ms.h_work + ms.d_off * const.h_target) / (ms.d_work + ms.d_off))
OVER (ORDER BY ms.c_month ROWS BETWEEN 2 PRECEDING AND CURRENT ROW))::numeric(10,2)
AS h_off
FROM monthly_sums AS ms
CROSS JOIN const
)
SELECT
calc.c_month,
calc.d_work,
calc.d_off,
calc.d_total,
calc.h_work,
calc.h_off,
(d_off * lag(h_off, 1, const.h_target) OVER (ORDER BY c_month)) AS h_off_sum,
(h_work + d_off * lag(h_off, 1, const.h_target) OVER (ORDER BY c_month)) AS h_sum
FROM calc CROSS JOIN const;
...给出以下结果:
c_month | d_work | d_off | d_total | h_work | h_off | h_off_sum | h_sum
---------+--------+-------+---------+--------+-------+-----------+--------
2018-12 | 16 | 5 | 21 | 150.25 | 9.06 | 40.0 | 190.25
2019-01 | 20 | 3 | 23 | 171.25 | 8.77 | 27.18 | 198.43
2019-02 | 15 | 5 | 20 | 120.5 | 8.52 | 43.85 | 164.35
(3 rows)
对于依赖于前一行值 (lag) 的列的第一行和第二行计算正确,但每天的平均小时数计算显然是错误的,因为我无法弄清楚如何提供当前行值 (h_sum) 返回到新 h_off 的计算中。
想要的结果应该如下:
c_month | d_work | d_off | d_total | h_work | h_off | h_off_sum | h_sum
---------+--------+-------+---------+--------+-------+-----------+--------
2018-12 | 16 | 5 | 21 | 150.25 | 9.06 | 40.0 | 190.25
2019-01 | 20 | 3 | 23 | 171.25 | 8.84 | 27.18 | 198.43
2019-02 | 15 | 5 | 20 | 120.5 | 8.64 | 44.2 | 164.7
(3 rows)
...意思是h_off 用于下个月的h_off_sum 和生成的h_sum 和h_sum 的可用月份(最多三个)反过来导致计算当前月份的@987654331 @(基本上是 avg(h_sum / d_total) 最多三个月)。
所以,实际计算是:
c_month | calculation | h_off
---------+----------------------------------------------------+-------
| | 8.00 << initial
.---------------------- uses ---------------------^
2018-12 | ((190.25 / 21)) / 1 | 9.06
.------------ uses ---------------^
2019-01 | ((190.25 / 21) + (198.43 / 23)) / 2 | 8.84
.--- uses --------^
2019-02 | ((190.25 / 21) + (198.43 / 23) + (164.7 / 20)) / 3 | 8.64
P.S.:我使用的是 PostgreSQL 11,所以如果有什么不同的话,我手头有最新的功能。
【问题讨论】:
标签: postgresql