簡體   English   中英

如何計算Oracle中兩個日期之間的of年數?

[英]How to calculate number of leap years between two dates in Oracle?

我想計算雇員的雇用日期和當前日期之間的of年數(在Oracle SQL Developer中的hr.employees表中)。 這個怎么做?

年包括366天。 我假設兩個日期之間的“ le年”由一年的1月1日至12月31日(即2月29日)的所有日期組成。

基於這種理解,有一個非常簡單的解決方案。

  • 計算雇用日期后一年的1月1日到結束日期一年的1月1日之間的天數。
  • 計算這兩個日期之間的年數。
  • 減去天數與年數之間的差* 365

幸運的是,內置功能可以完成大部分工作。

結果是:

   (trunc(sysdate, 'YYYY') -
    trunc(hiredate + interval '1' year, 'YYYY') -
    365 * (extract(year from sysdate) - extract(year from hiredate) - 1)
   ) as num_years

計算leap日數有點棘手,但這不是問題要問的。

您可以重用Oracle已經編寫的代碼:只需檢查創建a日是否引發異常:

SELECT TO_DATE('2016-02-29','YYYY-MM-DD') FROM DUAL;
29.02.2016 

SELECT TO_DATE('2018-02-29','YYYY-MM-DD') FROM DUAL;
ORA-01839: date not valid for month specified

因此,您只需要計算例外:

CREATE OR REPLACE FUNCTION count_leap_years (p_from DATE, p_to DATE) RETURN NUMBER 
IS
  number_of_leap_days NUMBER := 0;
  date_not_valid EXCEPTION;
  PRAGMA EXCEPTION_INIT(date_not_valid, -1839);
BEGIN
  FOR y IN EXTRACT(YEAR FROM p_from) .. EXTRACT(YEAR FROM p_to) LOOP
    DECLARE
      d DATE;
    BEGIN
      d := TO_DATE(to_char(y,'fm0000')||'-02-29', 'YYYY-MM-DD');
      IF p_from < d AND d < p_to THEN
        number_of_leap_days := number_of_leap_days + 1;
      END IF;
    EXCEPTION WHEN date_not_valid THEN 
      NULL;
    END;
  END LOOP;
  RETURN number_of_leap_days;
END count_leap_years;
/

在這種情況下,您可以選擇1到2999之間的數字。

    Select Rownum year
    From dual
    Connect By Rownum <= 2999

這樣的事情將允許您檢查特定年份是否為a年

CASE WHEN ((MOD(YEAR, 4) = 0 AND (MOD(YEAR, 100) <> 0)) OR MOD(year, 400) = 0) THEN 1 ELSE 0 END as isLeapYear

現在,您只需要添加過濾和the年的總和。

Select sum(isLeapYear)
from (
    Select year, CASE WHEN ((MOD(YEAR, 4) = 0 AND (MOD(YEAR, 100) <> 0)) OR MOD(year, 400) = 0) THEN 1 ELSE 0 END as isLeapYear
FROM (
    Select Rownum year
    From dual
    Connect By Rownum <= 2999
    ) a
    Where a.year >= EXTRACT(YEAR FROM DATE %DateStart%) and a.year <= EXTRACT(YEAR FROM DATE %DateEnd%)
) b

就性能而言,這確實可以得到改善,但是像這樣,我認為它更容易理解每​​個步驟在做什么,然后您可以將其分解為您真正想要和期望的東西。

嘗試這個:

CREATE OR REPLACE FUNCTION LEAP_YEARS(EMP_ID IN NUMBER)
RETURN NUMBER
IS 

HIRE_YEAR NUMBER:=0;
SYS_YEAR  NUMBER:=0;
NUMBER_LEAP_YEARS NUMBER:=0;

BEGIN
 SELECT EXTRACT(YEAR FROM HIRE_DATE) INTO HIRE_YEAR
 FROM EMPLOYEE
 WHERE EMPLOYEE_ID = EMP_ID;

 SELECT EXTRACT(YEAR FROM SYSDATE()) INTO SYS_YEAR
 FROM DUAL;

 FOR IDX IN HIRE_YEAR..SYS_YEAR LOOP
    IF MOD(IDX,4)=0 THEN
        NUMBER_LEAP_YEARS := NUMBER_LEAP_YEARS  + 1;
    END IF;
 END LOOP;

RETURN NUMBER_LEAP_YEARS;
END;

我在一個玩具示例上對其進行了測試,並且可以正常工作。 也許您需要改進它(提示:也許它需要一些例外,並且它假設hire_date <sysdate)。

然后,您可以將其用作:

SELECT LEAP_YEARS(E.EMPLOYEE_ID) FROM EMPLOYEE E;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM