Oracle эквивалент SQL Server / Sybase DateDiff - PullRequest
5 голосов
/ 04 сентября 2008

Сейчас мы используем NHibernate для подключения к другой базе данных, на которой установлено наше программное обеспечение. Поэтому я портирую многие процедуры SQL в Oracle.

В SQL Server есть замечательная функция DateDiff, которая принимает часть даты, начальную дату и конечную дату.

Примеры частей даты: день, неделя, месяц, год и т. Д. ,

Что такое эквивалент Oracle?

Я не нашел одну, мне нужно создать свою собственную версию?

(обновление от Марка Харрисона) Есть несколько хороших ответов, которые объясняют арифметику дат Oracle. Если вам нужен Oracle datediff (), смотрите ответ Эйнштейна. (Это необходимо для совместимости сценариев spme SQL между Sybase и Oracle.) Обратите внимание, что этот вопрос в равной степени относится и к Sybase.

Ответы [ 4 ]

4 голосов
/ 07 сентября 2008

Джон Лавуа - тебе это не нужно. DATE в Oracle - это тип данных даты и времени. Единственная разница между DATE и TIMESTAMP заключается в том, что DATE разрешается с точностью до секунды, а TIMESTAMP - с точностью до микросекунды. Поэтому статья Ask Tom также подходит для столбцов TIMESTAMP.

4 голосов
/ 24 ноября 2008

Я украл большую часть этого из старой статьи Тома несколько лет назад, исправил некоторые ошибки в статье и очистил ее. Разграничительные линии для datediff рассчитываются по-разному для Oracle и MSSQL, поэтому вам следует быть осторожным с некоторыми примерами, которые не учитывают границы стиля MSSQL / Sybase, которые не дают дробных результатов.

С помощью следующего вы сможете использовать синтаксис MSSQL и получать те же результаты, что и MSSQL, например SELECT DATEDIFF (dd, getdate (), DATEADD (dd, 5, getdate ())) FROM DUAL;

Я утверждаю только, что это работает - не то, что это эффективно или лучший способ сделать это. Я не являюсь человеком Oracle :) И вы могли бы подумать дважды об использовании моих функциональных макросов для обхода ситуации, когда требуются кавычки вокруг dd, mm, hh, mi..etc.

(обновление от Марка Харрисона) добавлена ​​функция dy в качестве псевдонима для dd.

CREATE OR REPLACE FUNCTION GetDate 
RETURN date IS today date;
BEGIN
RETURN(sysdate);
END;
/

CREATE OR REPLACE FUNCTION mm RETURN VARCHAR2 IS BEGIN RETURN('mm'); END;
/
CREATE OR REPLACE FUNCTION yy RETURN VARCHAR2 IS BEGIN RETURN('yyyy'); END;
/
CREATE OR REPLACE FUNCTION dd RETURN VARCHAR2 IS BEGIN RETURN('dd'); END;
/
CREATE OR REPLACE FUNCTION dy RETURN VARCHAR2 IS BEGIN RETURN('dd'); END;
/
CREATE OR REPLACE FUNCTION hh RETURN VARCHAR2 IS BEGIN RETURN('hh'); END;
/
CREATE OR REPLACE FUNCTION mi RETURN VARCHAR2 IS BEGIN RETURN('mi'); END;
/
CREATE OR REPLACE FUNCTION ss RETURN VARCHAR2 IS BEGIN RETURN('ss'); END;
/

CREATE OR REPLACE Function DateAdd(date_type IN varchar2, offset IN integer, date_in IN date )
RETURN date IS date_returned date;
BEGIN
date_returned := CASE date_type
    WHEN 'mm'   THEN add_months(date_in,TRUNC(offset))
    WHEN 'yyyy' THEN add_months(date_in,TRUNC(offset) * 12)
    WHEN 'dd'   THEN date_in + TRUNC(offset)
    WHEN 'hh'   THEN date_in + (TRUNC(offset) / 24)
    WHEN 'mi'   THEN date_in + (TRUNC(offset) /24/60)
    WHEN 'ss'   THEN date_in + (TRUNC(offset) /24/60/60)
    END;
RETURN(date_returned);
END;
/

CREATE OR REPLACE Function DateDiff( return_type IN varchar2, date_1 IN date, date_2 IN date)
RETURN integer IS number_return integer;
BEGIN
number_return := CASE return_type
    WHEN 'mm'   THEN ROUND(MONTHS_BETWEEN(TRUNC(date_2,'MM'),TRUNC(date_1, 'MM')))
    WHEN 'yyyy' THEN ROUND(MONTHS_BETWEEN(TRUNC(date_2,'YYYY'), TRUNC(date_1, 'YYYY')))/12
    WHEN 'dd'   THEN ROUND((TRUNC(date_2,'DD') - TRUNC(date_1, 'DD')))
    WHEN 'hh'   THEN (TRUNC(date_2,'HH') - TRUNC(date_1,'HH')) * 24
    WHEN 'mi'   THEN (TRUNC(date_2,'MI') - TRUNC(date_1,'MI')) * 24 * 60
    WHEN 'ss'   THEN (date_2 - date_1) * 24 * 60 * 60
    END;
RETURN(number_return);
END;
/
1 голос
/ 04 сентября 2008

Статья Тома очень старая. Здесь обсуждается только тип DATE. Если вы используете типы TIMESTAMP, арифметика даты встроена в PL / SQL.

http://www.akadia.com/services/ora_date_time.html

DECLARE
ts_a timestamp;
ts_b timestamp;
diff interval day to second;
BEGIN
  ts_a := systimestamp;
  ts_b := systimestamp-1/24;
  diff := ts_a - ts_b;
  dbms_output.put_line(diff);
END;
+00 01:00:00.462000

или

DECLARE
ts_b timestamp;
ts_a timestamp;
date_part interval day to second;

BEGIN
  ts_a := systimestamp;
  date_part := to_dsinterval('0 01:23:45.678');
  ts_b := ts_a + date_part;
  dbms_output.put_line(ts_b);
END;

04-SEP-08 05.00.38.108000 PM
0 голосов
/ 20 октября 2014

ВЫ могли бы написать для этого в оракуле функцию

function        datediff( p_what in varchar2, p_d1 in date, p_d2 in date) return number as  l_result    number; 
BEGIN
      select (p_d2-p_d1) * 
             decode( upper(p_what), 'SS', 24*60*60, 'MI', 24*60, 'HH', 24, NULL ) 
       into l_result from dual; 

      return l_result; 
END;

и используйте его как:

DATEDIFF('YYYY-MM-DD', SYSTIMESTAMP, SYSTIMESTAMP)
...