我在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。
请帮助!
答案 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.