Oracle 11g计算从开始日期到现在的星期一和星期四的数量

时间:2018-05-31 19:27:20

标签: oracle oracle11g

在Oracle中,我想构建一个查询,计算从开始日期算起的星期一和星期四的数量。

例如:

20-MAY-18 今天(星期四 - 5月31日 - 18日)

从5月20日至今,已经过了4个星期一和星期四(2个星期一和2个星期四)的总数。我希望在此查询中返回4。如果这个查询昨天(星期三30-MAY-18)运行,我想获得3个计数。

我想减去今天减去 20-MAY-18

的几周

也许是这样的:

select ( TRUNC( SYSDATE, 'IW' ) - TRUNC( TO_DATE('20-MAY-18'), 'IW' ) ) / 7 * 2 from dual;

由于星期一和星期四,我两次乘以它。如果星期六还没有出现,那么由于本周它会给出错误的结果。

我无法指望将本周过去的工作日计算到按周数计算的时间。

我还需要能够改变选定的日期,而不是只在星期一和星期四被困住。

2 个答案:

答案 0 :(得分:1)

您可以使用它来计算值:

计算包含开始日期的星期一与本周一之间的完整天数:

( TRUNC( SYSDATE, 'IW' ) - TRUNC( start_date, 'IW' ) )

除以7以获得整周的数量:

 / 7

将它乘以您希望每周匹配的天数

* 2

然后调整它以删除在开始日期之前计算的星期一和星期四。如果开始日是星期一,则为0调整,周二至周四为1,周五至周日为2:

- DECODE( TRUNC( start_date ) - TRUNC( start_date, 'IW' ),
          0, 0, -- Monday
          1, 1, -- Tuesday
          2, 1, -- Wednesday
          3, 1, -- Thursday
          4, 2, -- Friday
          5, 2, -- Saturday
          6, 2  -- Sunday
        )

然后调整它以包括从当前周一到今天的日期:

+ DECODE( TRUNC( SYSDATE ) - TRUNC( SYSDATE, 'IW' ),
          0, 1, -- Monday
          1, 1, -- Tuesday
          2, 1, -- Wednesday
          3, 2, -- Thursday
          4, 2, -- Friday
          5, 2, -- Saturday
          6, 2  -- Sunday
        )

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE table_name ( start_date ) AS
SELECT DATE '2018-05-20' + LEVEL - 1
FROM DUAL
CONNECT BY DATE '2018-05-20' + LEVEL - 1 <= SYSDATE;

查询1

SELECT start_date,
       TO_CHAR( start_date, 'DY' ) As day,
       ( TRUNC( SYSDATE, 'IW' ) - TRUNC( start_date, 'IW' ) ) / 7 * 2
       - DECODE( TRUNC( start_date ) - TRUNC( start_date, 'IW' ),
                0, 0, 1, 1, 2, 1, 3, 1, 4, 2, 5, 2, 6, 2 )
       + DECODE( TRUNC( SYSDATE ) - TRUNC( SYSDATE, 'IW' ),
                0, 1, 1, 1, 2, 1, 3, 2, 4, 2, 5, 2, 6, 2 ) AS num_mon_and_thurs
FROM   table_name

<强> Results

|           START_DATE | DAY | NUM_MON_AND_THURS |
|----------------------|-----|-------------------|
| 2018-05-20T00:00:00Z | SUN |                 4 |
| 2018-05-21T00:00:00Z | MON |                 4 |
| 2018-05-22T00:00:00Z | TUE |                 3 |
| 2018-05-23T00:00:00Z | WED |                 3 |
| 2018-05-24T00:00:00Z | THU |                 3 |
| 2018-05-25T00:00:00Z | FRI |                 2 |
| 2018-05-26T00:00:00Z | SAT |                 2 |
| 2018-05-27T00:00:00Z | SUN |                 2 |
| 2018-05-28T00:00:00Z | MON |                 2 |
| 2018-05-29T00:00:00Z | TUE |                 1 |
| 2018-05-30T00:00:00Z | WED |                 1 |
| 2018-05-31T00:00:00Z | THU |                 1 |
  

如果我想改变它而不是星期一和星期四是星期三,星期三,星期六怎么办?我该怎么做?

SELECT start_date,
       TO_CHAR( start_date, 'DY' ) As day,
       ( TRUNC( SYSDATE, 'IW' ) - TRUNC( start_date, 'IW' ) ) / 7 * 3
       - DECODE( TRUNC( start_date ) - TRUNC( start_date, 'IW' ),
                0, 0, 1, 0, 2, 1, 3, 2, 4, 2, 5, 2, 6, 3 )
       + DECODE( TRUNC( SYSDATE ) - TRUNC( SYSDATE, 'IW' ),
                0, 0, 1, 1, 2, 2, 3, 2, 4, 2, 5, 3, 6, 3 ) AS num_tue_wed_sat
FROM   table_name;

SQLFIDDLE

答案 1 :(得分:1)

也许这会有所帮助。您可以为其添加更多逻辑。我不知道为什么如果在5月30日跑步,必须返回3。他的想法是什么?无论何时运行,您的开始/结束日期都是相同的,并且天数之间也是相同的。如果他5月30日跑步会怎么样?

WITH mon_thur AS
(
SELECT to_date('20-MAY-2018') + LEVEL-1 start_date
     , to_date('31-MAY-2018') end_date
     , to_date('31-MAY-2018') - to_date('20-MAY-2018') days_between
 FROM dual
CONNECT BY LEVEL <= to_date('31-MAY-2018') - to_date('20-MAY-2018')+1  -- days_between+1
)
SELECT count(*) number_of_mon_thu FROM
(
SELECT start_date, to_char(start_date, 'D') d_date 
  FROM mon_thur
)
WHERE d_date IN (2, 4)
/

输出为4.您可以替换&#39; D&#39;格式化为&#39; DY&#39;并用WHERE d_date IN替换2,4(&#39; MON&#39;,&#39; THU&#39;)。