Oracle SQL去掉星期天,只考虑6个工作日

huangapple go评论73阅读模式
英文:

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) &lt;= x.dlvry_kpi THEN
        CASE
            WHEN x.dlvry_kpi - (
                -- Full weeks from Monday of start week to Monday of current week
                (TRUNC(SYSDATE, &#39;IW&#39;) - TRUNC(x.bkg_date + 1, &#39;IW&#39;)) * 6 / 7
                -- Add extra days in the current week excluding Sunday
                + CASE WHEN TRUNC(SYSDATE) - TRUNC(SYSDATE, &#39;IW&#39;) + 1 &lt;= 6 THEN TRUNC(SYSDATE) - TRUNC(SYSDATE, &#39;IW&#39;) + 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, &#39;IW&#39;) &lt;= 6 THEN TRUNC(x.bkg_date + 1) - TRUNC(x.bkg_date + 1, &#39;IW&#39;) ELSE 6 END
            ) &lt;= 0 THEN &#39;00 days left&#39;
            ELSE
                TO_CHAR(
                    x.dlvry_kpi - (
                        -- Full weeks from Monday of start week to Monday of current week
                        (TRUNC(SYSDATE, &#39;IW&#39;) - TRUNC(x.bkg_date + 1, &#39;IW&#39;)) * 6 / 7
                        -- Add extra days in the current week excluding Sunday
                        + CASE WHEN TRUNC(SYSDATE) - TRUNC(SYSDATE, &#39;IW&#39;) + 1 &lt;= 6 THEN TRUNC(SYSDATE) - TRUNC(SYSDATE, &#39;IW&#39;) + 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, &#39;IW&#39;) &lt;= 6 THEN TRUNC(x.bkg_date + 1) - TRUNC(x.bkg_date + 1, &#39;IW&#39;) ELSE 6 END
                    )
                ) || &#39; days left&#39;
        END
    ELSE &#39;OKPI&#39;
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, &#39;IW&#39;) WHEN 5 THEN 2 ELSE 1 END

For the sample data:

CREATE TABLE table_name (bkg_date, dlvry_kpi) AS
  SELECT TRUNC(SYSDATE, &#39;IW&#39;) + 8 - LEVEL, 1 FROM DUAL CONNECT BY LEVEL &lt;= 15;

Then:

SELECT bkg_date,
       next_bkg_date,
       dlvry_kpi,
       TRUNC(SYSDATE) AS today,
       (TRUNC(next_bkg_date, &#39;IW&#39;) - TRUNC(SYSDATE, &#39;IW&#39;)) * 6 / 7 AS full_weeks,
       LEAST(TRUNC(next_bkg_date) - TRUNC(next_bkg_date, &#39;IW&#39;), 5) AS days_at_end,
       LEAST(TRUNC(SYSDATE) - TRUNC(SYSDATE, &#39;IW&#39;), 5) AS day_at_start,
       -- Full weeks from Monday of current week to Monday of end week
       (TRUNC(next_bkg_date, &#39;IW&#39;) - TRUNC(SYSDATE, &#39;IW&#39;)) * 6 / 7
       -- Add extra days in the end week excluding Sunday
       + LEAST(TRUNC(next_bkg_date) - TRUNC(next_bkg_date, &#39;IW&#39;), 5)
       -- Subtract days in the current week before the today excluding Sunday
       - LEAST(TRUNC(SYSDATE) - TRUNC(SYSDATE, &#39;IW&#39;), 5) AS days
FROM   (
  SELECT bkg_date,
         bkg_date + CASE TRUNC(bkg_date) - TRUNC(bkg_date, &#39;IW&#39;) 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 &lt; -dlvry_kpi
       THEN &#39;OKPI&#39;
       ELSE TO_CHAR(dlvry_kpi + days, &#39;FM90&#39;) || &#39; days left&#39;
       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, &#39;IW&#39;) - TRUNC(SYSDATE, &#39;IW&#39;)) * 6 / 7
         -- Add extra days in the end week excluding Sunday
         + LEAST(TRUNC(next_bkg_date) - TRUNC(next_bkg_date, &#39;IW&#39;), 5)
         -- Subtract days in the current week before the today excluding Sunday
         - LEAST(TRUNC(SYSDATE) - TRUNC(SYSDATE, &#39;IW&#39;), 5) AS days
  FROM   (
    SELECT bkg_date,
           bkg_date + CASE TRUNC(bkg_date) - TRUNC(bkg_date, &#39;IW&#39;) 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

fiddle

huangapple
  • 本文由 发表于 2023年7月17日 13:45:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/76701762.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定