Как сравнить два значения DATE, основанные только на части даты в Oracle? - PullRequest
11 голосов
/ 15 сентября 2011

Я пытаюсь получить счет за последние 30 дней с помощью следующего запроса -

SELECT date_occured, COUNT(*) FROM problem
WHERE date_occured >= (CURRENT_DATE - 30)
GROUP BY date_occured;

//date_occured field is of type DATE.

По сути, в своем запросе я пытаюсь сравнить только часть даты в условии date_occured >= (CURRENT_DATE - 30), но, похоже, тоже сравнивает время.

Я попробовал TRUNC следующим образом -

TRUNC(date_occured) >= TRUNC(CURRENT_DATE - 30)

Но при запуске запроса он никогда не возвращается.

Я тоже пробовал -

SELECT date_occured, COUNT(*) FROM problem    
GROUP BY date_occured
HAVING TRUNC(date_occured) >= TRUNC(CURRENT_DATE - 30);

Опять это никогда не вернется.

Как можно сравнить только части даты из двух значений DATE в Oracle?

Ответы [ 5 ]

15 голосов
/ 15 сентября 2011

Для этого условия вам нужно только TRUNC с правой стороны:

WHERE date_occured >= TRUNC(CURRENT_DATE - 30)

Почему? Поскольку, если TRUNC (date_occured) позже, чем TRUNC (CURRENT_DATE - 30), то любой момент времени после TRUNC (date_occured) обязательно должен быть позже TRUNC (CURRENT_DATE - 30).

Очевидно, всегда верно, что date_occured> = TRUNC (date_occured) (подумайте об этом).

Логика говорит, что если A> = B и B> = C, то A> = C

Теперь подставьте:

  • A: date_occured
  • B: TRUNC (date_occured)
  • C: TRUNC (CURRENT_DATE - 30)
3 голосов
/ 15 сентября 2011

Я думаю, вы захотите обрезать и в выбранной части:

 SELECT TRUNC(date_occured) AS short_date_occured, COUNT(*)
 FROM problem 
 WHERE date_occured >= trunc(SYSDATE- 30) 
 GROUP BY short_date_occured;
1 голос
/ 15 сентября 2011

Я склонен подозревать, что Тони прав, и что вы действительно хотите только TRUNC в правой части выражения.

Если вы хотите TRUNC обе стороны выражения и у вас возникают проблемы с производительностью, вам, вероятно, нужен индекс на основе функций

CREATE INDEX idx_problem_trunc_dt_occured
    ON problem( trunc( date_occurred ) );

Это позволит вашему исходному запросу использовать индекс на основе функций.

1 голос
/ 15 сентября 2011

Попробуйте использовать SYSDATE против CURRENT_DATE. Sysdate использует местное время сервера, где CURRENT_DATE возвращает текущую дату / время для сервера по местному времени подключения клиента.

0 голосов
/ 13 декабря 2018

Вот подход, ориентированный на индекс.

вам не нужно использовать функции для столбцов, если вы используете функцию Oracle Native MONTHS_BETWEEN.

Возвращает разницу в количестве месяцев. Дни также указываются как разница, но с точки зрения точности, поэтому я предпочел использовать предложение BETWEEN

WHERE MONTHS_BETWEEN(date_occured, CURRENT_DATE - 30) BETWEEN 0 AND 1
...