英文:
Oracle SQL remove Sunday and consider only 6 working days
问题
我尝试了这个SQL CASE语句来获取距离超过KPI(OKPI)的剩余天数。
有两个主要条件让我感到困惑,
1- 移除或不考虑星期日作为工作日。
2- 实际的bkg_date是在1天之后。所以,例如,如果bkg_date = '2023年7月8日',那么bkg_date将是'2023年7月10日'。
CASE
WHEN SYSDATE - (x.bkg_date + 1) <= x.dlvry_kpi THEN
CASE
WHEN x.dlvry_kpi - (
-- 从开始周的星期一到当前周的星期一的完整周
(TRUNC(SYSDATE,'IW') - TRUNC(x.bkg_date + 1,'IW'))* 6/7
-- 在当前周添加额外的天数,不包括星期日
+ CASE WHEN TRUNC(SYSDATE) - TRUNC(SYSDATE,'IW') + 1 <= 6 THEN TRUNC(SYSDATE) - TRUNC(SYSDATE,'IW') + 1 ELSE 6 END
-- 在开始日期之前的那一周减去星期日之外的天数
- CASE WHEN TRUNC(x.bkg_date + 1) - TRUNC(x.bkg_date + 1,'IW') <= 6 THEN TRUNC(x.bkg_date + 1) - TRUNC(x.bkg_date + 1,'IW') ELSE 6 END
) <= 0 THEN '剩余0天'
ELSE
TO_CHAR(
x.dlvry_kpi - (
-- 从开始周的星期一到当前周的星期一的完整周
(TRUNC(SYSDATE,'IW') - TRUNC(x.bkg_date + 1,'IW'))* 6/7
-- 在当前周添加额外的天数,不包括星期日
+ CASE WHEN TRUNC(SYSDATE) - TRUNC(SYSDATE,'IW') + 1 <= 6 THEN TRUNC(SYSDATE) - TRUNC(SYSDATE,'IW') + 1 ELSE 6 END
-- 在开始日期之前的那一周减去星期日之外的天数
- CASE WHEN TRUNC(x.bkg_date + 1) - TRUNC(x.bkg_date + 1,'IW') <= 6 THEN TRUNC(x.bkg_date + 1) - TRUNC(x.bkg_date + 1,'IW') ELSE 6 END
)
) || '天剩余'
END
ELSE 'OKPI'
END AS AGING
所以,这是我想出的,并对以下输入给出结果OKPI:
x.bkg_date = '2023年7月8日';
sysdate = '2023年7月17日';
x.dlvry_kpi = 7
英文:
I tried this SQL CASE to get number of days left for Over KPI(OKPI).
There are 2 main conditions which are confusing me,
1- Remove or don't consider Sunday as a working day.
2- Actual bkg_date is after 1 day. So for example if bkg_date = '08 Jul 2023' then bkg_date will be = '10 Jul 2023'
CASE
WHEN SYSDATE - (x.bkg_date + 1) <= x.dlvry_kpi THEN
CASE
WHEN x.dlvry_kpi - (
-- Full weeks from Monday of start week to Monday of current week
(TRUNC(SYSDATE, 'IW') - TRUNC(x.bkg_date + 1, 'IW')) * 6 / 7
-- Add extra days in the current week excluding Sunday
+ CASE WHEN TRUNC(SYSDATE) - TRUNC(SYSDATE, 'IW') + 1 <= 6 THEN TRUNC(SYSDATE) - TRUNC(SYSDATE, 'IW') + 1 ELSE 6 END
-- Subtract days in the week before the start date excluding Sunday
- CASE WHEN TRUNC(x.bkg_date + 1) - TRUNC(x.bkg_date + 1, 'IW') <= 6 THEN TRUNC(x.bkg_date + 1) - TRUNC(x.bkg_date + 1, 'IW') ELSE 6 END
) <= 0 THEN '00 days left'
ELSE
TO_CHAR(
x.dlvry_kpi - (
-- Full weeks from Monday of start week to Monday of current week
(TRUNC(SYSDATE, 'IW') - TRUNC(x.bkg_date + 1, 'IW')) * 6 / 7
-- Add extra days in the current week excluding Sunday
+ CASE WHEN TRUNC(SYSDATE) - TRUNC(SYSDATE, 'IW') + 1 <= 6 THEN TRUNC(SYSDATE) - TRUNC(SYSDATE, 'IW') + 1 ELSE 6 END
-- Subtract days in the week before the start date excluding Sunday
- CASE WHEN TRUNC(x.bkg_date + 1) - TRUNC(x.bkg_date + 1, 'IW') <= 6 THEN TRUNC(x.bkg_date + 1) - TRUNC(x.bkg_date + 1, 'IW') ELSE 6 END
)
) || ' days left'
END
ELSE 'OKPI'
END AS AGING
So, this is what I've come up with and gives the result OKPI for following inputs;
x.bkg_date = '08 Jul 2023'
sysdate = '17 Jul 2023'
x.dlvry_kpi = 7
答案1
得分: 0
您可以使用以下SQL代码来查找下一个工作日(跳过星期日):
bkg_date + CASE TRUNC(bkg_date) - TRUNC(bkg_date, 'IW') WHEN 5 THEN 2 ELSE 1 END
对于示例数据:
CREATE TABLE table_name (bkg_date, dlvry_kpi) AS
SELECT TRUNC(SYSDATE, 'IW') + 8 - LEVEL, 1 FROM DUAL CONNECT BY LEVEL <= 15;
然后:
SELECT bkg_date,
next_bkg_date,
dlvry_kpi,
TRUNC(SYSDATE) AS today,
(TRUNC(next_bkg_date, 'IW') - TRUNC(SYSDATE, 'IW')) * 6 / 7 AS full_weeks,
LEAST(TRUNC(next_bkg_date) - TRUNC(next_bkg_date, 'IW'), 5) AS days_at_end,
LEAST(TRUNC(SYSDATE) - TRUNC(SYSDATE, 'IW'), 5) AS day_at_start,
-- 从本周星期一到结束周星期一的完整周数
(TRUNC(next_bkg_date, 'IW') - TRUNC(SYSDATE, 'IW')) * 6 / 7
-- 添加结束周的额外天数,不包括星期日
+ LEAST(TRUNC(next_bkg_date) - TRUNC(next_bkg_date, 'IW'), 5)
-- 减去今天之前的本周天数,不包括星期日
- LEAST(TRUNC(SYSDATE) - TRUNC(SYSDATE, 'IW'), 5) AS days
FROM (
SELECT bkg_date,
bkg_date + CASE TRUNC(bkg_date) - TRUNC(bkg_date, 'IW') WHEN 5 THEN 2 ELSE 1 END as next_bkg_date,
dlvry_kpi
FROM table_name
)
输出结果如下:
BKG_DATE | NEXT_BKG_DATE | DLVRY_KPI | TODAY | FULL_WEEKS | DAYS_AT_END | DAY_AT_START | DAYS |
---|---|---|---|---|---|---|---|
2023-07-24 00:00:00 (MON) | 2023-07-25 00:00:00 (TUE) | 1 | 2023-07-17 00:00:00 (MON) | 6 | 1 | 0 | 7 |
2023-07-23 00:00:00 (SUN) | 2023-07-24 00:00:00 (MON) | 1 | 2023-07-17 00:00:00 (MON) | 6 | 0 | 0 | 6 |
2023-07-22 00:00:00 (SAT) | 2023-07-24 00:00:00 (MON) | 1 | 2023-07-17 00:00:00 (MON) | 6 | 0 | 0 | 6 |
2023-07-21 00:00:00 (FRI) | 2023-07-22 00:00:00 (SAT) | 1 | 2023-07-17 00:00:00 (MON) | 0 | 5 | 0 | 5 |
2023-07-20 00:00:00 (THU) | 2023-07-21 00:00:00 (FRI) | 1 | 2023-07-17 00:00:00 (MON) | 0 | 4 | 0 | 4 |
2023-07-19 00:00:00 (WED) | 2023-07-20 00:00:00 (THU) | 1 | 2023-07-17 00:00:00 (MON) | 0 | 3 | 0 | 3 |
2023-07-18 00:00:00 (TUE) | 2023-07-19 00:00:00 (WED) | 1 | 2023-07-17 00:00:00 (MON) | 0 | 2 | 0 | 2 |
2023-07-17 00:00:00 (MON) | 2023-07-18 00:00:00 (TUE) | 1 | 2023-07-17 00:00:00 (MON) | 0 | 1 | 0 | 1 |
2023-07-16 00:00:00 (SUN) | 2023-07-17 00:00:00 (MON) | 1 | 2023-07-17 00:00:00 (MON) | 0 | 0 | 0 | 0 |
2023-07-15 00:00:00 (SAT) | 2023-07-17 00:00:00 (MON) | 1 | 2023-07-17 00:00:00 (MON) | 0 | 0 | 0 | 0 |
2023-07-14 00:00:00 (FRI) | 2023-07-15 00:00:00 (SAT) | 1 | 2023-07-17 00:00:00 (MON) | -6 | 5 | 0 | -1 |
2023-07-13 00:00:00 (THU) | 2023-07-14 00:00:00 (FRI) | 1 | 2023-07-17 00:00:00 (MON) | -6 | 4 | 0 | -2 |
2023-07-12 00:00:00 (WED) | 2023-07-13 00:00:00 (THU) | 1 | 2023-07-17 00:00:00 (MON) | -6 | 3 | 0 | -3 |
2023-07-11 00:00:00 (TUE) | 2023-07-12 00:00:00 (WED) | 1 | 2023-07-17 00:00:00 (MON) | -6 | 2 | 0 | -4 |
2023-07-10 00:00:00 (MON) | 2023-07-11 00:00:00 (TUE) | 1 | 2023-07-17 00 |
英文:
You can find the next business day (skipping Sundays) using:
bkg_date + CASE TRUNC(bkg_date) - TRUNC(bkg_date, 'IW') WHEN 5 THEN 2 ELSE 1 END
For the sample data:
CREATE TABLE table_name (bkg_date, dlvry_kpi) AS
SELECT TRUNC(SYSDATE, 'IW') + 8 - LEVEL, 1 FROM DUAL CONNECT BY LEVEL <= 15;
Then:
SELECT bkg_date,
next_bkg_date,
dlvry_kpi,
TRUNC(SYSDATE) AS today,
(TRUNC(next_bkg_date, 'IW') - TRUNC(SYSDATE, 'IW')) * 6 / 7 AS full_weeks,
LEAST(TRUNC(next_bkg_date) - TRUNC(next_bkg_date, 'IW'), 5) AS days_at_end,
LEAST(TRUNC(SYSDATE) - TRUNC(SYSDATE, 'IW'), 5) AS day_at_start,
-- Full weeks from Monday of current week to Monday of end week
(TRUNC(next_bkg_date, 'IW') - TRUNC(SYSDATE, 'IW')) * 6 / 7
-- Add extra days in the end week excluding Sunday
+ LEAST(TRUNC(next_bkg_date) - TRUNC(next_bkg_date, 'IW'), 5)
-- Subtract days in the current week before the today excluding Sunday
- LEAST(TRUNC(SYSDATE) - TRUNC(SYSDATE, 'IW'), 5) AS days
FROM (
SELECT bkg_date,
bkg_date + CASE TRUNC(bkg_date) - TRUNC(bkg_date, 'IW') WHEN 5 THEN 2 ELSE 1 END as next_bkg_date,
dlvry_kpi
FROM table_name
)
Outputs:
BKG_DATE | NEXT_BKG_DATE | DLVRY_KPI | TODAY | FULL_WEEKS | DAYS_AT_END | DAY_AT_START | DAYS |
---|---|---|---|---|---|---|---|
2023-07-24 00:00:00 (MON) | 2023-07-25 00:00:00 (TUE) | 1 | 2023-07-17 00:00:00 (MON) | 6 | 1 | 0 | 7 |
2023-07-23 00:00:00 (SUN) | 2023-07-24 00:00:00 (MON) | 1 | 2023-07-17 00:00:00 (MON) | 6 | 0 | 0 | 6 |
2023-07-22 00:00:00 (SAT) | 2023-07-24 00:00:00 (MON) | 1 | 2023-07-17 00:00:00 (MON) | 6 | 0 | 0 | 6 |
2023-07-21 00:00:00 (FRI) | 2023-07-22 00:00:00 (SAT) | 1 | 2023-07-17 00:00:00 (MON) | 0 | 5 | 0 | 5 |
2023-07-20 00:00:00 (THU) | 2023-07-21 00:00:00 (FRI) | 1 | 2023-07-17 00:00:00 (MON) | 0 | 4 | 0 | 4 |
2023-07-19 00:00:00 (WED) | 2023-07-20 00:00:00 (THU) | 1 | 2023-07-17 00:00:00 (MON) | 0 | 3 | 0 | 3 |
2023-07-18 00:00:00 (TUE) | 2023-07-19 00:00:00 (WED) | 1 | 2023-07-17 00:00:00 (MON) | 0 | 2 | 0 | 2 |
2023-07-17 00:00:00 (MON) | 2023-07-18 00:00:00 (TUE) | 1 | 2023-07-17 00:00:00 (MON) | 0 | 1 | 0 | 1 |
2023-07-16 00:00:00 (SUN) | 2023-07-17 00:00:00 (MON) | 1 | 2023-07-17 00:00:00 (MON) | 0 | 0 | 0 | 0 |
2023-07-15 00:00:00 (SAT) | 2023-07-17 00:00:00 (MON) | 1 | 2023-07-17 00:00:00 (MON) | 0 | 0 | 0 | 0 |
2023-07-14 00:00:00 (FRI) | 2023-07-15 00:00:00 (SAT) | 1 | 2023-07-17 00:00:00 (MON) | -6 | 5 | 0 | -1 |
2023-07-13 00:00:00 (THU) | 2023-07-14 00:00:00 (FRI) | 1 | 2023-07-17 00:00:00 (MON) | -6 | 4 | 0 | -2 |
2023-07-12 00:00:00 (WED) | 2023-07-13 00:00:00 (THU) | 1 | 2023-07-17 00:00:00 (MON) | -6 | 3 | 0 | -3 |
2023-07-11 00:00:00 (TUE) | 2023-07-12 00:00:00 (WED) | 1 | 2023-07-17 00:00:00 (MON) | -6 | 2 | 0 | -4 |
2023-07-10 00:00:00 (MON) | 2023-07-11 00:00:00 (TUE) | 1 | 2023-07-17 00:00:00 (MON) | -6 | 1 | 0 | -5 |
And to get the number of days left then:
SELECT bkg_date,
dlvry_kpi,
days,
CASE
WHEN days < -dlvry_kpi
THEN 'OKPI'
ELSE TO_CHAR(dlvry_kpi + days, 'FM90') || ' days left'
END AS aging
FROM (
SELECT bkg_date,
dlvry_kpi,
-- Full weeks from Monday of current week to Monday of end week
(TRUNC(next_bkg_date, 'IW') - TRUNC(SYSDATE, 'IW')) * 6 / 7
-- Add extra days in the end week excluding Sunday
+ LEAST(TRUNC(next_bkg_date) - TRUNC(next_bkg_date, 'IW'), 5)
-- Subtract days in the current week before the today excluding Sunday
- LEAST(TRUNC(SYSDATE) - TRUNC(SYSDATE, 'IW'), 5) AS days
FROM (
SELECT bkg_date,
bkg_date + CASE TRUNC(bkg_date) - TRUNC(bkg_date, 'IW') WHEN 5 THEN 2 ELSE 1 END as next_bkg_date,
dlvry_kpi
FROM table_name
)
)
Which outputs:
BKG_DATE | DLVRY_KPI | DAYS | AGING |
---|---|---|---|
2023-07-24 00:00:00 (MON) | 1 | 7 | 8 days left |
2023-07-23 00:00:00 (SUN) | 1 | 6 | 7 days left |
2023-07-22 00:00:00 (SAT) | 1 | 6 | 7 days left |
2023-07-21 00:00:00 (FRI) | 1 | 5 | 6 days left |
2023-07-20 00:00:00 (THU) | 1 | 4 | 5 days left |
2023-07-19 00:00:00 (WED) | 1 | 3 | 4 days left |
2023-07-18 00:00:00 (TUE) | 1 | 2 | 3 days left |
2023-07-17 00:00:00 (MON) | 1 | 1 | 2 days left |
2023-07-16 00:00:00 (SUN) | 1 | 0 | 1 days left |
2023-07-15 00:00:00 (SAT) | 1 | 0 | 1 days left |
2023-07-14 00:00:00 (FRI) | 1 | -1 | 0 days left |
2023-07-13 00:00:00 (THU) | 1 | -2 | OKPI |
2023-07-12 00:00:00 (WED) | 1 | -3 | OKPI |
2023-07-11 00:00:00 (TUE) | 1 | -4 | OKPI |
2023-07-10 00:00:00 (MON) | 1 | -5 | OKPI |
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论