数据准备:
CREATE TABLE test_work_day
(
work_day integer ,
send_date DATE ,
volume integer,
week_day varchar,
hols varchar
);
insert into test_work_day values
(0, '2022-05-21', 0, 'Saturday',null),
(0, '2022-05-22', 0, 'Sunday',null),
(1, '2022-05-23', 0, 'Monday',null),
(1, '2022-05-24', 99, 'Tuesday',null),
(1, '2022-05-25', 111,'Wednesday',null),
(0, '2022-05-26', 154, 'Thursday', 'Public_holiday' ),
(1, '2022-05-27', 200, 'Friday',null),
(0, '2022-05-28', 0, 'Saturday',null),
(0, '2022-05-29', 0, 'Sunday',null),
(0, '2022-05-30', 0, 'Monday', 'Public_holiday'),
(1, '2022-05-31', 164, 'Tuesday',null),
(1, '2022-06-01', 123, 'Wednesday',null),
(1, '2022-06-02', 189, 'Thursday',null),
(1, '2022-06-03', 150, 'Friday',null),
(0, '2022-06-04', 0, 'Saturday',null),
(0, '2022-06-05', 0, 'Sunday',null),
(1, '2022-06-06', 100, 'Monday',null),
(1, '2022-06-07', 200, 'Tuesday',null);
select * from test_work_day;
输出:
当“work_day”列中的值 = 0 时,“volume”列中的值(以及后续值)应向下移动到“work_day”列中的值 = 1 的点。如果连续有 3 个 0该值应移至 work_day = 1 的第一行。交易量应仅与 work_day = 1 对齐
从第一个 work_day = 0 (26/05/2022) 算起的第 8 个日历日,有一个追赶时刻,将前一个值和当前值相加。
所需输出:
提前非常感谢!
您的预期结果与您的解释并不完全一致,但这读起来就像一个间隙和岛屿问题,其中每个岛都是一个工作日,之前可能有许多非工作日。
我们可以用窗口总和来识别岛屿(技巧是按降序日期对分区进行排序以匹配您想要的逻辑),然后使用条件表达式:
select work_day, send_date, volume,
case when work_day = 1 then sum(volume) over(partition by grp) else volume end as new_volume
from (
select t.*, sum(work_day) over(order by send_date desc) as grp
from test_work_day t
) t
order by send_date
工作日 | 发送日期 | 音量 | 新卷 |
---|---|---|---|
1 | 2022-05-24 | 99 | 99 |
1 | 2022-05-25 | 111 | 111 |
0 | 2022-05-26 | 154 | 154 |
1 | 2022-05-27 | 200 | 354 |
0 | 2022-05-28 | 0 | 0 |
0 | 2022-05-29 | 0 | 0 |
0 | 2022-05-30 | 0 | 0 |
1 | 2022-05-31 | 164 | 164 |
1 | 2022-06-01 | 123 | 123 |
0 | 2022-06-02 | 189 | 189 |
0 | 2022-06-03 | 150 | 150 |
1 | 2022-06-04 | 0 | 339 |
1 | 2022-06-05 | 0 | 0 |
1 | 2022-06-06 | 100 | 100 |
1 | 2022-06-07 | 200 | 200 |
如果支持WITH表达式:
;WITH cteShiftIndex AS
(
SELECT work_day,
send_date,
volume,
CASE WHEN Volume = 0 THEN NULL
ELSE ROW_NUMBER() OVER
(PARTITION BY (CASE WHEN Volume = 0 THEN 0 ELSE 1 END) ORDER BY send_date ASC)
END AS RowIndex,
SUM(work_day) OVER (ORDER BY send_date) AS WorkIndex
FROM test_work_day
)
SELECT
cte.work_day,
cte.send_date,
cte.Volume,
CASE WHEN cte.work_day = 0
THEN 0 ELSE cte2.volume
END AS VolumeAdjusted
FROM cteShiftIndex cte
LEFT JOIN cteShiftIndex cte2 ON cte.WorkIndex = cte2.RowIndex
ORDER BY cte.send_date
已更新(带有 SUM 逻辑)
;WITH cteShiftIndex AS
(
SELECT work_day,
send_date,
volume,
CASE WHEN Volume = 0 THEN NULL
ELSE ROW_NUMBER() OVER
(PARTITION BY (CASE WHEN Volume = 0 THEN 0 ELSE 1 END) ORDER BY send_date ASC)
END AS RowIndex,
SUM(work_day) OVER (ORDER BY send_date) AS WorkIndex
FROM test_work_day
)
, cteGroupedShiftIndex AS
(
SELECT *,
SUM(volume) OVER (ORDER BY send_date) AS TotalVolume,
DENSE_RANK() OVER (ORDER BY CEILING(WorkIndex / 7.0)) AS GroupIndex
FROM cteShiftIndex
)
SELECT
cte.work_day,
cte.send_date,
cte.Volume,
CASE WHEN cte.work_day = 0 THEN 0
WHEN cte.WorkIndex % 7 = 0 THEN -- to do the SUM every 7th working day
cte2.Volume +
SUM(cte.Volume) OVER (PARTITION BY cte2.GroupIndex ORDER BY cte.send_date) -
SUM(CASE WHEN cte.work_day = 0
THEN 0
ELSE cte2.volume END) OVER (PARTITION BY cte2.GroupIndex ORDER BY cte.send_date)
ELSE cte2.volume
END AS VolumeAdjusted
FROM cteGroupedShiftIndex cte
LEFT JOIN cteGroupedShiftIndex cte2 ON (cte.WorkIndex + cte.GroupIndex - 1) = cte2.RowIndex
ORDER BY cte.send_date