Оракул дата "Между" Запрос - PullRequest
51 голосов
/ 03 марта 2010

Я использую базу данных оракула. Я хочу выполнить один запрос для проверки данных между двумя датами.

NAME               START_DATE    
-------------    ------------- 
Small Widget       15-JAN-10 04.25.32.000000 PM      
Product 1          17-JAN-10 04.31.32.000000 PM  



select * from <TABLENAME> where start_date  
BETWEEN '15-JAN-10' AND '17-JAN-10'

Но я не получаю никаких результатов от вышеупомянутого запроса. Я думаю, что я должен использовать «как» и «%». Но я не знаю, где их использовать. Пожалуйста, включите немного света на это.

спасибо заранее.

Ответы [ 5 ]

81 голосов
/ 03 марта 2010

Судя по вашему выводу, похоже, что вы определили START_DATE как метку времени. Если бы это была обычная дата, Oracle мог бы справиться с неявным преобразованием. Но поскольку вам не нужно явно приводить эти строки к датам.

SQL> alter session set nls_date_format = 'dd-mon-yyyy hh24:mi:ss'
  2  /

Session altered.

SQL>
SQL> select * from t23
  2  where start_date between '15-JAN-10' and '17-JAN-10'
  3  /

no rows selected

SQL> select * from t23
  2  where start_date between to_date('15-JAN-10') and to_date('17-JAN-10')
  3  /

WIDGET                          START_DATE
------------------------------  ----------------------
Small Widget                    15-JAN-10 04.25.32.000    

SQL> 

Но у нас все еще только один ряд. Это потому, что START_DATE имеет элемент времени. Если мы не укажем компонент времени, Oracle по умолчанию установит его на полночь. Это хорошо для стороны от стороны BETWEEN, но не для стороны до :

SQL> select * from t23
  2  where start_date between to_date('15-JAN-10') 
  3                       and to_date('17-JAN-10 23:59:59')
  4  /

WIDGET                          START_DATE
------------------------------  ----------------------
Small Widget                    15-JAN-10 04.25.32.000
Product 1                       17-JAN-10 04.31.32.000

SQL>

редактировать

Если вы не можете передать компонент времени, есть несколько вариантов. Одним из них является изменение предложения WHERE для удаления элемента времени из критериев:

where trunc(start_date) between to_date('15-JAN-10') 
                            and to_date('17-JAN-10')

Это может повлиять на производительность, поскольку дисквалифицирует любой индекс b-дерева на START_DATE. Вместо этого вам нужно будет создать индекс на основе функций.

В качестве альтернативы вы можете добавить элемент времени к дате в вашем коде:

where start_date between to_date('15-JAN-10') 
                     and to_date('17-JAN-10') + (86399/86400) 

Из-за этих проблем многие люди предпочитают избегать использования between, проверяя границы дат следующим образом:

where start_date >= to_date('15-JAN-10') 
and start_date < to_date('18-JAN-10')
22 голосов
/ 03 марта 2010

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

SELECT *
FROM <TABLENAME>
WHERE start_date BETWEEN TO_DATE('2010-01-15','YYYY-MM-DD') AND TO_DATE('2010-01-17', 'YYYY-MM-DD');

Отредактировано для работы в указанном формате:

SELECT *
FROM <TABLENAME>
WHERE start_date BETWEEN TO_DATE('15-JAN-10','DD-MON-YY') AND TO_DATE('17-JAN-10','DD-MON-YY');
3 голосов
/ 03 марта 2010

Как правильно указал APC, ваш столбец start_date выглядит как TIMESTAMP, но это может быть также TIMESTAMP с локальным TIMEZONE или TIMESTAMP с TIMEZONE типом данных. Это может оказать влияние на любые запросы, которые вы выполняете к данным, если ваш сервер баз данных находится в другом часовом поясе. Однако давайте будем простыми и предположим, что вы находитесь в том же часовом поясе, что и ваш сервер. Во-первых, чтобы дать вам уверенность, проверьте, что start_date является типом данных TIMESTAMP.

Используйте команду SQLPlus DESCRIBE (или эквивалент в вашей IDE), чтобы убедиться, что этот столбец является типом данных TIMESTAMP.

например

ОПИСАТЬ mytable

Должен сообщить:

Name        Null? Type
----------- ----- ------------
NAME              VARHAR2(20) 
START_DATE        TIMESTAMP

Если он указан как Type = TIMESTAMP, вы можете запросить диапазоны дат с самым простым преобразованием даты TO_TIMESTAMP, для которого не требуется аргумент (или картинка).

Мы используем TO_TIMESTAMP, чтобы оптимизатор рассмотрел любой индекс в столбце START_DATE. В ответе APC также отмечалось, что для этого столбца мог быть создан индекс на основе функций, и это могло бы повлиять на предикат SQL, но мы не можем комментировать это в этом запросе. Если вы хотите узнать, как узнать, какие индексы были применены к таблице, опубликуйте еще один вопрос, и мы ответим на него отдельно.

Итак, при условии, что для start_date имеется индекс, который является типом данных TIMESTAMP, и вы хотите, чтобы оптимизатор его учел, ваш SQL будет:

select * from mytable where start_date between to_timestamp('15-JAN-10') AND to_timestamp('17-JAN-10')+.9999999

+. 999999999 очень близко к, но не совсем 1, поэтому конверсия 17-ЯНВ-10 будет в этот день как можно ближе к полуночи, поэтому вы запрашиваете обе строки.

База данных будет видеть МЕЖДУ с 15-JAN-10 00: 00: 00: 0000000 до 17-JAN-10 23: 59: 59: 99999 и будет поэтому включите все даты с 15, 16 и 17 января 2010 года независимо от временной составляющей временной метки.

Надеюсь, это поможет.

Dazzer

1 голос
/ 30 марта 2015

Также можно использовать следующий запрос:

select * 
  from t23
 where trunc(start_date) between trunc(to_date('01/15/2010','mm/dd/yyyy')) and trunc(to_date('01/17/2010','mm/dd/yyyy'))
1 голос
/ 26 июня 2014

Дата между запросами

SELECT *
    FROM emp
    WHERE HIREDATE between to_date (to_char(sysdate, 'yyyy') ||'/09/01', 'yyyy/mm/dd')
    AND to_date (to_char(sysdate, 'yyyy') + 1|| '/08/31', 'yyyy/mm/dd');
...