Oracle查询可从给定的数据集中获取一周的结束时间

时间:2018-11-13 03:11:50

标签: sql oracle

我在Oracle中有一个表,其中EOW列表示一周的结束时间。 我想写一个查询以获取最近的星期几。

表格校准

DAY         DAY OFTHE WEEK      EOW

20181026    FRI                 Y  
20181027    SAT                 N  
20181028    SUN                 N  
20181029    MON                 N  
20181030    TUE                 N   -->
20181031    WED                 N  
20181101    THU                 N  
20181102    FRI                 Y  -->  
20181103    SAT                 N  

所以当我

select DAY , "logic" from cal where day = 20181030;

什么是“逻辑”,以便在这种情况下我能获得最近的星期几 20181026。

请帮助!

3 个答案:

答案 0 :(得分:0)

我猜是,

 If the date is 30-OCT-2018 (20181030), then you want last friday date as 26-OCT - 2018 (20181026). 

另一种情况:

If the date is 27-OCT-2018 (20181027), in that case also you want last friday date which is 26-OCT - 2018 (20181026).

如果我的猜测是正确的,那么下面的查询可能会起作用:

   WITH TEMP1 AS
            (
             SELECT TO_CHAR(
                            TO_DATE('20181030','YYYYMMDD') ,'DD-MON-YY') AS DATE_TEST 
               FROM DUAL
             ) 
   SELECT next_day (TO_DATE(DATE_TEST,'DD-MON-YY')-7,'FRIDAY') Last_Friday
     FROM   TEMP1;

它将显示为:

   LAST_FRIDAY
   26-OCT-18

以后您可以将其转换为所需格式。

测试用例2

   WITH TEMP1 AS
        (
         SELECT TO_CHAR(
                        TO_DATE('20181103','YYYYMMDD') ,'DD-MON-YY') AS DATE_TEST 
           FROM DUAL
         ) 
   SELECT next_day (TO_DATE(DATE_TEST,'DD-MON-YY')-7,'FRIDAY') Last_Friday
 FROM   TEMP1;

输出:

 LAST_FRIDAY
 02-NOV-18

现在打破以上查询:

在CTE中使用了WITH子句。

  WITH TEMP1 AS
    (
     SELECT TO_CHAR(
                    TO_DATE('20181103','YYYYMMDD') ,'DD-MON-YY') AS DATE_TEST 
       FROM DUAL
     )

在这里,TO_DATE('20181103','YYYYMMDD'),'DD-MON-YY'-会将20181103转换为2018年11月3日。

因此,WITH子句的结果(这是03-NOV-2018)将在另一个查询中使用:

SELECT next_day (TO_DATE(DATE_TEST,'DD-MON-YY')-7,'FRIDAY') Last_Friday
  FROM   TEMP1;

此处DATE_TEST从with子句输出。首先

 TO_DATE(DATE_TEST,'DD-MON-YY')-7

从提到的日期开始需要花费之前的7天(当前日期为DATE_TEST:03-NOV -2018),所以从2018年11月03日开始需要花费最后7天的时间。

假设:

DATE        DAY       Order
28-10-2018  SUN         1
29-10-2018  MON         2
30-10-2018  TUE         3
31-10-2018  WED         4
01-11-2018  THURS       5
02-11-2018  FRI         6
03-11-2018  SAT         7

我们得到了上面提到的所有7天。

next_day (TO_DATE(DATE_TEST,'DD-MON-YY')-7,'FRIDAY') 

现在从第二天开始,我们可以再改一天,在这里,我们通过在参数中提及来请求FRIDAY。所以星期五是02-11-2018。

因此输出将为02-11-2018。

答案 1 :(得分:0)

您真的需要一个 fixed 表吗? CTE可以轻松创建您想要的任何日历,因此-我获得了这种自由来制作类似这样的东西。

我逐步编写了它,以便您可以跟踪它的执行情况。从第一个CTE(dates)开始,然后转到day_diff,依此类推。看来您正在选择当前日期之前的第一个FRI。因为,对于20181030,最接近的周末不是20181026(到周五的4天),而是20181102(到周五的3天)。

最后,结果是

SQL> with dates as
  2    (select
  3      -- add "level" (sequence of numbers from 1 to 60) to 1st of previous month
  4      trunc(add_months(sysdate, - 1), 'mm') + level - 1 datum,
  5      -- convert that date into a day name (MON, FRI, ...)
  6      to_char(trunc(add_months(sysdate, -1), 'mm') + level - 1, 'DY',
  7              'NLS_DATE_LANGUAGE=ENGLISH') dan,
  8      -- if day name is FRI, set EOW = Y. Else, it is N
  9      case when to_char(trunc(add_months(sysdate, -1), 'mm') + level - 1, 'DY',
 10                        'NLS_DATE_LANGUAGE=ENGLISH') = 'FRI' then 'Y'
 11           else 'N'
 12      end eow
 13     from dual
 14     connect by level <= 60  -- my CTE will have 60 dates; yours can have any number
 15    ),
 16  day_diff as
 17    (select datum, dan, eow,
 18       datum - to_date('&par_datum', 'dd.mm.yyyy') diff
 19    from dates
 20    ),
 21  diff_only_eow as
 22    (select datum, dan, eow, diff,
 23       row_number() over (order by diff desc) rn
 24     from day_diff
 25     where eow = 'Y'
 26       and diff <= 0
 27    )
 28  select datum, dan, eow, diff, rn
 29  from diff_only_eow
 30  where rn = 1;
Enter value for par_datum: 30.10.2018

DATUM    DAN          E       DIFF         RN
-------- ------------ - ---------- ----------
20181026 FRI          Y         -4          1

SQL>

答案 2 :(得分:0)

这可能会解决您的查询

select day, to_char(to_date(day,'YYYYMMDD'),'DY') f1,
    case to_char(to_date(day,'YYYYMMDD'),'DY')
        when 'FRI' then 0
        when 'SAT' then -1
        when 'SUN' then -2
        when 'MON' then -3
        when 'TUE' then 3
        when 'WED' then 2
        when 'THU' then 1
    end as f2,
    to_char(to_date(day,'YYYYMMDD')+ case to_char(to_date(day,'YYYYMMDD'),'DY')
        when 'FRI' then 0
        when 'SAT' then -1
        when 'SUN' then -2
        when 'MON' then -3
        when 'TUE' then 3
        when 'WED' then 2
        when 'THU' then 1
    end,'YYYYMMDD') as f3
from test_cal;


DAY      F1                F2 F3
-------- --------- ---------- --------
20181026 FRI                0 20181026
20181027 SAT               -1 20181026
20181028 SUN               -2 20181026
20181029 MON               -3 20181026
20181030 TUE                3 20181102
20181031 WED                2 20181102
20181101 THU                1 20181102
20181102 FRI                0 20181102
20181103 SAT               -1 20181102

9 rows selected.