如何在不使用to_date、trunc 和预定义add_months函数的情况下获取上个月的第一个和最后一个日期



我写了下面的代码,但我没有得到预期的输出:

SQL> select TO_CHAR(TO_CHAR(sysdate,'MM')-1,'DD-MM-YYYY') AS PREV_MON_FIRST,
TO_CHAR(TO_CHAR(sysdate,'MM'),'DD-MM-YYYY')-1 AS PREV_MON_LAST from dual;
select TO_CHAR(TO_CHAR(sysdate,'MM')-1,'DD-MM-YYYY') AS PREV_MON from dual
*
ERROR at line 1:
ORA-01481: invalid number format model

缺少"DD"和"YYYY"值是正确的,但是当我尝试仅检索月份时,它也显示了相同的错误

您可以使用以下解决方案:

SELECT
TRUNC(LAST_DAY(ADD_MONTHS(sysdate, -2))) + 1 AS first_date,
TRUNC(LAST_DAY(ADD_MONTHS(sysdate, -1))) AS last_date
FROM dual

如果格式适合您的需求,则仅使用TO_CHAR选择上个月的第一天YYYYMMDD很容易:

SQL> select (to_char(sysdate, 'yyyymm') - 1) || '01' first_day
2  from dual;
FIRST_DAY
------------------------------------------
20180701
SQL>

但是,最后一天 - 我不知道。


通常的方法是有效的,但涉及其他功能:

SQL> select trunc(add_months(sysdate, -1), 'mm') first_day,
2         trunc(sysdate, 'mm') - 1 last_day
3  from dual;
FIRST_DAY  LAST_DAY
---------- ----------
2018-07-01 2018-07-31
SQL>

对于LAST_DAY,这里是使用月份值hard_code而不使用 add_months,trunc,to_date 的查询

select to_char(sysdate,'yyyy')||
to_char(sysdate,'mm')-1||
case when to_char(sysdate,'mm')-1 in (1,3,5,7,8,10,12) THEN 31 
when to_char(sysdate,'mm')-1 in (4,6,9,11) THEN 30
when mod(to_char(sysdate,'yyyy'),4)=0 and to_char(sysdate,'mm')-1=2 THEN 29
when mod(to_char(sysdate,'yyyy'),4)!=0 and to_char(sysdate,'mm')-1=2 THEN 28
end 
from dual

如果我从字面上理解你的问题,一个解决方案是

CREATE OR REPLACE FUNCTION MY_LAST_DAY RETURN TIMESTAMP AS
next_run_date TIMESTAMP;
return_date_after TIMESTAMP := SYSTIMESTAMP - INTERVAL '100' DAY;
BEGIN
LOOP  
DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING('FREQ=DAILY;INTERVAL=1;BYMONTHDAY=-1', NULL, return_date_after, next_run_date);
EXIT WHEN EXTRACT(MONTH FROM next_run_date) = EXTRACT(MONTH FROM SYSTIMESTAMP);
return_date_after := next_run_date;
END LOOP;    
RETURN return_date_after;
END;
/
CREATE OR REPLACE FUNCTION MY_FIRST_DAY RETURN TIMESTAMP AS
next_run_date TIMESTAMP;
return_date_after TIMESTAMP := SYSTIMESTAMP - INTERVAL '100' DAY;
BEGIN
LOOP  
DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING('FREQ=DAILY;INTERVAL=1;BYMONTHDAY=1', NULL, return_date_after, next_run_date);
EXIT WHEN EXTRACT(MONTH FROM next_run_date) = EXTRACT(MONTH FROM SYSTIMESTAMP);
return_date_after := next_run_date;
END LOOP;    
RETURN return_date_after;
END;
/

它返回上个月的第一个和最后一个日期,而不使用TO_DATE(或TO_TIMESTAMP(、TRUNCADD_MONTHS

但我希望你同意你的问题相当愚蠢。

对于LAST_DAY,这里是使用月份值hard_code而不使用 add_months,trunc,to_date 的查询

选择 to_char(sysdate,'yyyy'(|| to_char(系统日期,"毫米"(-1|| 当to_char(系统日期,'mm'(-1 英寸 (1,3,5,7,8,10,12( 然后 31 当 to_char(sysdate,'mm'(-1 IN (4,6,9,11( 则 30 当 mod(to_char(sysdate,'yyyy'(,4(=0 且 to_char(sysdate,'mm'(-1=2 则 29 当 mod(to_char(sysdate,'yyyy'(,4(!=0 和 to_char(sysdate,'mm'(-1=2 则 28 结束 从双

用于处理 1 月和闰年的新查询:

Select Decode(to_char(sysdate,'mm'(,1,to_char(sysdate,'yyyy'(-1 ,to_char(sysdate,'yyyy'((|| 解码(to_char(sysdate,'mm'(,1,12, to_char(sysdate,'mm'(-1(|| 当 to_char(系统日期,'mm'(-1 英寸 (1,3,5,7,8,10,0( 然后 31 时的情况 当to_char(系统日期,'mm'(-1 英寸 (4,6,9,11( 然后 30 当 to_char(sysdate,'mm'(-1=2 AND MOD(to_char(sysdate,'yyyy'(,4(!=0 AND MOD(to_char(sysdate,'yyyy'(,400(!=0 则 29 其他 28 结束 从双

最新更新