问题描述
我希望这能够为我提供过去 12 个月(不包括周末)的日历日期列表;但它只是给了我完整的日期列表 - 我认为这很好 - 但想知道为什么下面不正确。
SELECT ADD_MONTHS(Trunc(SYSDATE,'MM'),-12) - 1 + rownum AS CalendarDate
FROM all_objects
WHERE ADD_MONTHS(Trunc(SYSDATE,-12) - 1 + rownum <= sysdate
AND to_char(sysdate,'DY') NOT IN ('SAT','SUN')
解决方法
您使用 to_char(sysdate,'DY') 检查今天是星期日还是星期一。您需要检查在您的窗口中不可用的 CalendarDate。您可以使用 cte 来计算日历,然后您可以按照以下条件删除周末。
with cte (CalendarDate) as
(
SELECT ADD_MONTHS(TRUNC(SYSDATE,'MM'),-12) - 1 + rownum AS CalendarDate
FROM all_objects
WHERE ADD_MONTHS(TRUNC(SYSDATE,-12) - 1 + rownum <= sysdate
)
select * from cte where
to_char(CalendarDate,'DY') not in ('SAT','SUN');
| CALENDARDATE | | :----------- | | 02-MAR-20 | | 03-MAR-20 | | 04-MAR-20 | | 05-MAR-20 | | 06-MAR-20 | | 09-MAR-20 | | 10-MAR-20 | | 11-MAR-20 | | 12-MAR-20 | | 13-MAR-20 | | 16-MAR-20 | | 17-MAR-20 | | 18-MAR-20 | | 19-MAR-20 | | 20-MAR-20 | | 23-MAR-20 | | 24-MAR-20 | | 25-MAR-20 | | 26-MAR-20 | | 27-MAR-20 | | 30-MAR-20 | | 31-MAR-20 | | 01-APR-20 | | 02-APR-20 | | 03-APR-20 | | 06-APR-20 | | 07-APR-20 | | 08-APR-20 | | 09-APR-20 | | 10-APR-20 | | 13-APR-20 | | 14-APR-20 | | 15-APR-20 | | 16-APR-20 | | 17-APR-20 | | 20-APR-20 | | 21-APR-20 | | 22-APR-20 | | 23-APR-20 | | 24-APR-20 | | 27-APR-20 | | 28-APR-20 | | 29-APR-20 | | 30-APR-20 | | 01-MAY-20 | | 04-MAY-20 | | 05-MAY-20 | | 06-MAY-20 | | 07-MAY-20 | | 08-MAY-20 | | 11-MAY-20 | | 12-MAY-20 | | 13-MAY-20 | | 14-MAY-20 | | 15-MAY-20 | | 18-MAY-20 | | 19-MAY-20 | | 20-MAY-20 | | 21-MAY-20 | | 22-MAY-20 | | 25-MAY-20 | | 26-MAY-20 | | 27-MAY-20 | | 28-MAY-20 | | 29-MAY-20 | | 01-JUN-20 | | 02-JUN-20 | | 03-JUN-20 | | 04-JUN-20 | | 05-JUN-20 | | 08-JUN-20 | | 09-JUN-20 | | 10-JUN-20 | | 11-JUN-20 | | 12-JUN-20 | | 15-JUN-20 | | 16-JUN-20 | | 17-JUN-20 | | 18-JUN-20 | | 19-JUN-20 | | 22-JUN-20 | | 23-JUN-20 | | 24-JUN-20 | | 25-JUN-20 | | 26-JUN-20 | | 29-JUN-20 | | 30-JUN-20 | | 01-JUL-20 | | 02-JUL-20 | | 03-JUL-20 | | 06-JUL-20 | | 07-JUL-20 | | 08-JUL-20 | | 09-JUL-20 | | 10-JUL-20 | | 13-JUL-20 | | 14-JUL-20 | | 15-JUL-20 | | 16-JUL-20 | | 17-JUL-20 | | 20-JUL-20 | | 21-JUL-20 | | 22-JUL-20 | | 23-JUL-20 | | 24-JUL-20 | | 27-JUL-20 | | 28-JUL-20 | | 29-JUL-20 | | 30-JUL-20 | | 31-JUL-20 | | 03-AUG-20 | | 04-AUG-20 | | 05-AUG-20 | | 06-AUG-20 | | 07-AUG-20 | | 10-AUG-20 | | 11-AUG-20 | | 12-AUG-20 | | 13-AUG-20 | | 14-AUG-20 | | 17-AUG-20 | | 18-AUG-20 | | 19-AUG-20 | | 20-AUG-20 | | 21-AUG-20 | | 24-AUG-20 | | 25-AUG-20 | | 26-AUG-20 | | 27-AUG-20 | | 28-AUG-20 | | 31-AUG-20 | | 01-SEP-20 | | 02-SEP-20 | | 03-SEP-20 | | 04-SEP-20 | | 07-SEP-20 | | 08-SEP-20 | | 09-SEP-20 | | 10-SEP-20 | | 11-SEP-20 | | 14-SEP-20 | | 15-SEP-20 | | 16-SEP-20 | | 17-SEP-20 | | 18-SEP-20 | | 21-SEP-20 | | 22-SEP-20 | | 23-SEP-20 | | 24-SEP-20 | | 25-SEP-20 | | 28-SEP-20 | | 29-SEP-20 | | 30-SEP-20 | | 01-OCT-20 | | 02-OCT-20 | | 05-OCT-20 | | 06-OCT-20 | | 07-OCT-20 | | 08-OCT-20 | | 09-OCT-20 | | 12-OCT-20 | | 13-OCT-20 | | 14-OCT-20 | | 15-OCT-20 | | 16-OCT-20 | | 19-OCT-20 | | 20-OCT-20 | | 21-OCT-20 | | 22-OCT-20 | | 23-OCT-20 | | 26-OCT-20 | | 27-OCT-20 | | 28-OCT-20 | | 29-OCT-20 | | 30-OCT-20 | | 02-NOV-20 | | 03-NOV-20 | | 04-NOV-20 | | 05-NOV-20 | | 06-NOV-20 | | 09-NOV-20 | | 10-NOV-20 | | 11-NOV-20 | | 12-NOV-20 | | 13-NOV-20 | | 16-NOV-20 | | 17-NOV-20 | | 18-NOV-20 | | 19-NOV-20 | | 20-NOV-20 | | 23-NOV-20 | | 24-NOV-20 | | 25-NOV-20 | | 26-NOV-20 | | 27-NOV-20 | | 30-NOV-20 | | 01-DEC-20 | | 02-DEC-20 | | 03-DEC-20 | | 04-DEC-20 | | 07-DEC-20 | | 08-DEC-20 | | 09-DEC-20 | | 10-DEC-20 | | 11-DEC-20 | | 14-DEC-20 | | 15-DEC-20 | | 16-DEC-20 | | 17-DEC-20 | | 18-DEC-20 | | 21-DEC-20 | | 22-DEC-20 | | 23-DEC-20 | | 24-DEC-20 | | 25-DEC-20 | | 28-DEC-20 | | 29-DEC-20 | | 30-DEC-20 | | 31-DEC-20 | | 01-JAN-21 | | 04-JAN-21 | | 05-JAN-21 | | 06-JAN-21 | | 07-JAN-21 | | 08-JAN-21 | | 11-JAN-21 | | 12-JAN-21 | | 13-JAN-21 | | 14-JAN-21 | | 15-JAN-21 | | 18-JAN-21 | | 19-JAN-21 | | 20-JAN-21 | | 21-JAN-21 | | 22-JAN-21 | | 25-JAN-21 | | 26-JAN-21 | | 27-JAN-21 | | 28-JAN-21 | | 29-JAN-21 | | 01-FEB-21 | | 02-FEB-21 | | 03-FEB-21 | | 04-FEB-21 | | 05-FEB-21 | | 08-FEB-21 | | 09-FEB-21 | | 10-FEB-21 | | 11-FEB-21 | | 12-FEB-21 | | 15-FEB-21 | | 16-FEB-21 | | 17-FEB-21 | | 18-FEB-21 | | 19-FEB-21 | | 22-FEB-21 | | 23-FEB-21 | | 24-FEB-21 | | 25-FEB-21 | | 26-FEB-21 | | 01-MAR-21 | | 02-MAR-21 | | 03-MAR-21 | | 04-MAR-21 | | 05-MAR-21 | | 08-MAR-21 | | 09-MAR-21 |
dbfiddle here
,因为你这样做:
AND to_char(sysdate,'DY') NOT IN ('SAT','SUN')
而且今天不是周六或周日。您需要查看计算出的 CalendarDate 值;但是您不能在同一级别的子查询中执行此操作。您可以尝试重新计算它:
AND to_char(ADD_MONTHS(TRUNC(SYSDATE,-12) - 1 + rownum,'SUN')
但这不会返回任何行 - 至少在当前运行时。碰巧的是,2020 年 3 月 1 日是星期日,因此被排除在外;并且由于 rownum
生成的时间和方式,该结果被排除,下一个看到相同的值,该值被排除,依此类推。
您可以使用内联视图来避免这两个问题:
SELECT CalendarDate
FROM (
SELECT ADD_MONTHS(TRUNC(SYSDATE,-12) - 1 + rownum AS CalendarDate
FROM all_objects
WHERE ADD_MONTHS(TRUNC(SYSDATE,-12) - 1 + rownum <= sysdate
)
WHERE to_char(CalendarDate,'DY','NLS_DATE_LANGUAGE=ENGLISH') NOT IN ('SAT','SUN')
CALENDARDATE
02-MAR-20
03-MAR-20
04-MAR-20
05-MAR-20
06-MAR-20
09-MAR-20
10-MAR-20
...
我添加了一个语言修饰符,以防止会话未设置为英语的用户出现不同的行为。
虽然查询 all_objects
并不理想,但最好使用分层查询:
SELECT *
FROM (
SELECT ADD_MONTHS(TRUNC(SYSDATE,-12) - 1 + level AS CalendarDate
FROM dual
CONNECT BY level <= TRUNC(SYSDATE) - ADD_MONTHS(TRUNC(SYSDATE,-12) + 1
)
WHERE to_char(CalendarDate,'SUN')
ORDER BY CalendarDate
或递归 CTE,如果您是 11gR2+:
WITH rcte (CalendarDate) AS (
SELECT ADD_MONTHS(TRUNC(SYSDATE,-12)
FROM dual
UNION ALL
SELECT rcte.CalendarDate + interval '1' day
FROM rcte
WHERE rcte.CalendarDate < TRUNC(SYSDATE)
)
SELECT CalendarDate
FROM rcte
WHERE to_char(CalendarDate,'SUN')
ORDER BY CalendarDate
db<>fiddle(作为 18c,以避免其使用的 11g 版本中的补丁级别出现一些问题)。