Сравнение дат в Oracle с использованием функции декодирования - PullRequest
7 голосов
/ 01 сентября 2010

Мне нужно сравнить две даты, используя функцию декодирования Oracle, чтобы определить, является ли одна из них less than or equal другой.

Я нашел эту статью - http://www.techonthenet.com/oracle/functions/decode.php

Какие состояния (приснизу) что нижеприведенная функция декодирования вернет date2, если date1> date2:

decode((date1 - date2) - abs(date1 - date2), 0, date2, date1)

Не вернет ли date2, если date1> = date2?

Или это просто, если date1> date2?

Есть ли более простое решение?

Ответы [ 6 ]

18 голосов
/ 01 сентября 2010

Эта функция вернет date2, если date2 <= date1.Подставляя значения и переводя их в псевдокод, вы получаете <code>if 0 - 0 = 0 then date2 else date1, где обе даты совпадают.

Лучшее решение, если вы используете 8i или более позднюю версию, это использовать case:

select case when date1 >= date2 then date2 else date1 end from Your_Table;

Так как case допускает операторы неравенства, он гораздо более читабелен.

7 голосов
/ 01 сентября 2010

@ Аллан уже дал мне лучшее решение, но если вы настаиваете на использовании функции decode, вы можете обработать результат функции sign вместо этого.

http://www.techonthenet.com/oracle/functions/sign.php

sign(a) возвращает -1, если a < 0, 0, если a = 0 и 1, если a > 0.Таким образом, следующая логика

if date1 >= date2 then
    return date1;
else
    return date2;
end if;

может быть переписана с использованием decode следующим образом:

select decode(sign(date2-date1), 
              -1 /*this means date 1 > date 2*/, date1 /* return date1*/, 
               0 /*dates are equal */,           date1 /* again, return date1*/,
               /*in any other case, which is date2 > date1, return date2*/ date2) 
from dual;
1 голос
/ 02 сентября 2010

Если вы пытаетесь проверить по дате - то есть каждый раз в 1/1 меньше 1/2, а каждый в 1/1 равен любому другому в 1/1, даже если OracleДАТА больше - тогда вы хотите сравнить следующим образом:

TRUNC (DATE1) <= TRUNC (DATE2) </p>

Я не вижу этого в других ответах, это настолько просто, чтозаставляет задуматься, не понимаю ли я вопрос.

1 голос
/ 01 сентября 2010

Вы можете попробовать функцию months_between.Он вычислит количество месяцев между двумя датами в виде десятичного числа.

select months_between(sysdate+30, sysdate ) from dual;
select months_between(sysdate+15, sysdate ) from dual;

В этом примере первый параметр больше второго, поэтому он вернет 1. Вторая строка возвращает ~ 0,48 (при выполнении около 11:30 утра 2010-09-01) Чтобы получить фактические значения даты:

select case when months_between(sysdate+30, sysdate ) > 0 then sysdate+30 else sysdate end from dual;

В общем:

case when months_between(dateA, dateB ) > 0 then dateA else dateB

Обновление:

После некоторых экспериментов кажется, что самая тонкая гранулярность этой функции - Day.

select months_between(to_date('2010-10-16 23:59:59', 'YYYY-MM-DD HH24:MI:SS'),
                       to_date('2010-10-16 00:00:00', 'YYYY-MM-DD HH24:MI:SS'))
from dual;

... вернет 0

, но

select months_between(to_date('2010-10-17 00:00:00', 'YYYY-MM-DD HH24:MI:SS'),
                       to_date('2010-10-16 00:00:00', 'YYYY-MM-DD HH24:MI:SS'))
from dual;

вернет 0.032258064516129.

Некоторые другие интересные различия в датах / методы сравнения здесь: http://www.orafaq.com/faq/how_does_one_get_the_time_difference_between_two_date_columns

0 голосов
/ 16 сентября 2015

Это лучше:

decode(sign(trunc(sysdate) - (trunc(sysdate))), 1, 1, -1, -1, 0 , 0)

1: date 1 > date 2
0: date 1 = date 2
-1: date 1 < date 2
0 голосов
/ 01 сентября 2010

вернет дату2, когда дата1> = дата2

...