Как рассчитать количество високосных лет между двумя датами в Oracle? - PullRequest
0 голосов
/ 08 июня 2018

Я хочу рассчитать количество високосных лет между датой найма сотрудника и текущей датой (в таблице hr.employees в Oracle SQL Developer).Как это сделать?

Ответы [ 4 ]

0 голосов
/ 08 июня 2018

попробуйте это:

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

Тогда вы можете использовать его как:

SELECT LEAP_YEARS(E.EMPLOYEE_ID) FROM EMPLOYEE E;
0 голосов
/ 08 июня 2018

Вы можете повторно использовать код, который Oracle уже написал: просто проверьте, вызывает ли создание високосного дня исключение:

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;
/
0 голосов
/ 08 июня 2018

високосный год состоит из 366 дней.Я предполагаю, что «високосный год» между двумя датами состоит из всех дней с 1 января по 31 декабря года с 29 февраля.

Исходя из этого понимания, существует довольно простое решение.

  • Подсчитайте количество дней между 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

Подсчитать немного сложнее високосных дней но вопрос не в этом.

0 голосов
/ 08 июня 2018

Примерно так можно выбрать цифры, в данном случае от 1 до 2999.

    Select Rownum year
    From dual
    Connect By Rownum <= 2999

Примерно так можно проверить, является ли конкретный год високосным или нет

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

Теперь вам просто нужно добавить фильтрацию и сумму високосных лет.

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

Это может быть действительно улучшено с точки зрения производительности, но вот так я думаю, что это прощепоймите, что делает каждый шаг, и тогда вы сможете разложить его на то, что вы действительно хотите и ожидаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...