Oracle SQL: синтаксис для предложения WHERE с одной датой между двумя другими - PullRequest
0 голосов
/ 24 октября 2018

Заранее извиняюсь, чувствую, что я здесь упускаю что-то фундаментальное.

Я ограничиваю запрос, ГДЕ одно поле (уже в формате даты) находится между двумя другими:

SELECT Stuff
FROM Table
WHERE datefield BETWEEN (currentdate - 28) AND (current_date - 1)

Это ничего не возвращает.Теперь, если я явно отформатирую обе даты как даты и поищу одну дату:

SELECT Stuff FROM Table
WHERE TO_DATE(datefield, 'YYYY-MM-DD') = TO_DATE((current_date - 1), 'YYYY- 
MM-DD') 

, которая возвращает результаты одного дня, как и предполагалось.Однако, если я тогда попробую что-то вроде:

SELECT Stuff FROM Table
WHERE TO_DATE(datefield, 'YYYY-MM-DD') >= TO_DATE((current_date - 28),'YYYY- 
MM-DD') 

Это вернет всю таблицу, включая даты задолго до (current_date - 28)

И, наконец, если я попробую BETWEENпосле явного форматирования:

SELECT Stuff FROM Table
WHERE TO_DATE(datefield, 'YYYY-MM-DD') BETWEEN TO_DATE((current_date - 28) 
,'YYYY-MM-DD') AND TO_DATE((current_date - 1) ,'YYYY-MM-DD')

Это снова ничего не возвращает.

Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 24 октября 2018
SELECT Stuff
FROM   Table
WHERE  datefield BETWEEN (currentdate - 28) AND (current_date - 1)

Возвращает значения за 28 дней до текущей даты в то же время суток, что и сейчас, и за 1 день до текущей даты в то же время суток, что и сейчас.Таким образом, если вы введете этот параметр в 10:23 сегодня, то он получит результаты до 10:23 вчера, а если все ваши вчерашние результаты были введены во второй половине дня, то они не будут включены в результаты.

SELECT Stuff
FROM   Table
WHERE  TO_DATE(datefield, 'YYYY-MM-DD') = TO_DATE((current_date - 1), 'YYYY-MM-DD') 

TO_DATE( date_string, format_model ) принимает строку в качестве первого аргумента, поэтому Oracle неявно преобразует вашу дату в строку, используя параметр сеанса NLS_DATE_FORMAT.Таким образом, ваш запрос эффективен:

SELECT Stuff
FROM   Table
WHERE  TO_DATE(
         TO_CHAR(
           datefield,
           ( SELECT VALUE FROM NLS_SESSION_PARAMETERS WHERE PARAMETER = 'NLS_DATE_FORMAT' )
         ),
         'YYYY-MM-DD'
       )
       =
       TO_DATE(
         TO_CHAR(
           (current_date - 1),
           ( SELECT VALUE FROM NLS_SESSION_PARAMETERS WHERE PARAMETER = 'NLS_DATE_FORMAT' )
         ),
         'YYYY-MM-DD'
       ) 

Во-первых, никогда не полагайтесь на неявное преобразование.Во-вторых, в зависимости от того, что ваш параметр сеанса NLS_DATE_FORMAT, ваш запрос также: вызовет исключение, если модель формата не соответствует YYYY-MM-DD;или дайте вам бессмысленные даты (т. е. если ваша стандартная модель формата RR-MM-DD, то вы потеряете века от ваших дат; если это DD-MM-YY, то вы поменяете дни и годы - что может «работать» [т.е.поднять исключение] на следующее десятилетие или около того, а затем ужасно взорваться в феврале 2029 года);или это будет работать.Тем не менее, это параметр сеанса, поэтому пользователи могут его изменить, и ваш запрос случайным образом перестанет работать без изменения вашего SQL.

Если предположить, что ваш NLS_DATE_FORMAT равен YYYY-MM-DD, тогда это будет эффективно урезать ваши даты, и вы можетесделать это намного проще, используя:

SELECT Stuff
FROM   Table
WHERE  TRUNC(datefield) = TRUNC(current_date - 1)

Это позволит получить все результаты (независимо от времени суток) за вчерашний день.

То, что вы, вероятно, хотите:

SELECT Stuff
FROM   Table
WHERE  datefield >= TRUNC( currentdate - 28 )
AND    datefield <  TRUNC( current_date )

Поскольку все результаты будут получены с полуночи 28 дней назад до полуночи сегодня.


Если это не сработает, вам необходимо проверить значения даты:

SELECT TO_CHAR( datevalue, 'YYYY-MM-DD HH24:MI:SS' )
FROM   table;

Возможно, вы обнаружите, что даты хранятся вместе с годом в 1-м веке нашей эры (т. Е. 0018-10-24 09:50:00 в качестве значения), и это (вероятно) будет связано с тем, что даты были загружены в виде строки с двухзначным годом (YY-MM-DD) когда ожидается 4-значный год (YYYY-MM-DD), поэтому Oracle будет считать, что столетие равно 0.

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