Oracle — LAST_DAY и TRUNC — порядок выполнения

#oracle #datetime #plsql #oracle19c

Вопрос:

Я получаю неожиданный результат при использовании комбинации LAST_DAY и TRUNC :

 select LAST_DAY(TRUNC(sysdate, 'DAY')) from dual;
--31-JUL-2021 00:00:00

select TRUNC(LAST_DAY(sysdate), 'DAY')from dual;
--26-JUL-2021 00:00:00
 

Почему эти вызовы не возвращают одинаковые результаты? Я имею в виду, в чем разница между:

  1. Я хочу, чтобы сегодняшний день был усечен (избавьтесь от часов)
  2. Тогда получите последний день месяца

И

  1. Я хочу последний день месяца (с часом)
  2. А затем избавьтесь от часовой части

Комментарии:

1. Просто для того, чтобы подтвердить полученный ответ; в документации показано поведение для различных элементов формата. В нем также отмечается, что «ДЕНЬ» чувствителен к NLS.

Ответ №1:

TRUNC(datestamp, 'DAY') возвращает вам первый день недели, содержащий datestamp . Странно, но это правда.

Если вам нужен день метки даты, просто используйте TRUNC(datestamp) .

Метки даты Oracle-это числа с плавающей запятой под капотом.

Комментарии:

1. О боже, ты абсолютно прав с частью «ДЕНЬ»: D » DD » — это то, что я искал… Совершенно упустил это из виду. Спасибо!

2. @О. Джонс. небольшая поправка. Даты Oracle (метки времени) — это не числа с плавающей запятой, а внутренний байтовый массив целых чисел (7 байт для даты, 11-13 байт для меток времени). Видеть . Вы можете получить представление об select sysdate, dump(sysdate) from dual; этом, если верно, что арифметика дат в сочетании с арифметикой с плавающей запятой, поскольку 1 указывает на день, таким образом, половина дня равна .5, а четверть дня равна .25 и т. Д.