Дата SQL с фиксированным днем и месяцем, но относительным годом

#sql #oracle #datetime #business-objects #date-arithmetic

#sql #Oracle #дата и время #бизнес-объекты #дата-арифметика

Вопрос:

Я создал отчет в BusinessObjects WEBI, но я хотел бы настроить базовый SQL так, чтобы год в диапазоне дат менялся в зависимости от времени выполнения запроса, оставляя день и месяц неизменными

Этот пример …

 WHERE
ACT_ENDDT  BETWEEN  '01-10-2019 00:00:00'  AND  '30-09-2020 00:00:00'
 

… желательно, если бы я запустил запрос сейчас (текущий год -1 И текущий год соответственно), но если бы я должен был выполнить этот запрос в 2021 году, я хочу, чтобы эти годы изменились на 2020 и 2021 соответственно, сохраняя день и месяцы одинаковыми (10/1 и 9/30).

Я просмотрел несколько ресурсов, таких как sqltutorial и w3schools, но я едва ли новичок в этом и не могу понять, как заставить это работать. Я также попробовал решение, представленное здесь в потоке 28707795, как таковое:

 ACT_ENDDT  BETWEEN  DATEFROMPARTS(YEAR(getdate())-1,10,1) AND DATEFROMPARTS(YEAR(getdate()),9,30)
 

… но в итоге появляется сообщение о том, что DATEFROMPARTS является недопустимым идентификатором.

Есть ли способ жестко запрограммировать часть даты и прикрепить к ней модификатор только для года, например ... BETWEEN '01-10-'amp;[*currentyear* - 1] ... ?

Спасибо.

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

1. Пожалуйста, укажите в своем вопросе базу данных, которую вы используете: mysql, oracle, sqlserver …?

2. Примечание: ACT_ENDDT BETWEEN '01-10-2019 00:00:00' AND '30-09-2020 00:00:00' пропускает все моменты времени после 30-09-2020 00:00:00, даже если дневная часть по-прежнему равна 30-09-2020. Есть вероятность, что это не является преднамеренным и ACT_ENDDT >= '01-10-2019 00:00:00' AND ACT_ENDDT < '01-10-2020 00:00:00' является более подходящим выражением.

3. Что такое тип ACT_ENDDT данных? Если это строка, between она не будет работать. Если это `дата, это не то, как вы пишете литералы даты .

4. Хранятся ли ваши данные в базе данных Oracle? В Oracle нет таких функций, как DATEFROMPARTS и GETDATE. Если это действительно Oracle, и вы переходите из другого продукта базы данных, вам нужно будет изучить диалект Oracle. Отдельно от этого обратите пристальное внимание на обсуждение полузакрытых, полуоткрытых интервалов в ответе GMB; это очень распространенная ловушка для новичков. Убедитесь, что вы не пропустили даты (всегда даты-времена в Oracle!) с последнего дня вашего интервала. МЕЖДУ очень редко хорошо работает с интервалами дат.

Ответ №1:

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

 where act_enddt between trunc(sysdate, 'year') - interval '3' month
                    and trunc(sysdate, 'year')   interval '9' month - interval '1' day
 

Интересно, может ли быть полезен полуоткрытый интервал:

 where act_enddt >= trunc(sysdate, 'year') - interval '3' month
  and act_enddt <  trunc(sysdate, 'year')   interval '9' month
 

Разница между двумя выражениями заключается в том, что последнее допускает даты между 30 октября в 00:00 и концом этого дня. Если ваши даты не имеют временного компонента, это не имеет значения (а второе выражение немного аккуратнее).

Ответ №2:

Вы можете использовать extract() для извлечения части года sysdate , выполнить с ней арифметические действия, например, вычесть единицу, объединить часть месяца и дня, чтобы завершить ее представлением даты, и преобразовать эту строку в date with to_date() .

Это

 to_date(extract(YEAR FROM sysdate) - 1 || '-10-01', 'YYYY-MM-DD')
 

для вашего нижнего и

 to_date(extract(YEAR FROM sysdate) || '-09-30', 'YYYY-MM-DD')
 

для вашей верхней границы.