Как правильно обрабатывать даты в ограничениях запросов - PullRequest
1 голос
/ 02 февраля 2011

В настоящее время я использую следующий запрос, чтобы получить все проверки, сделанные в июне 2010 года:

select inspections.name
from inspections
where
  to_char(inspections.insp_date, 'YYYY') = 2010 and
  to_char(inspections.insp_date, 'MM') = 06;

но это немного неловко. Разве не было бы лучшего способа сделать это? Глядя на http://infolab.stanford.edu/~ullman/fcdb/oracle/or-time.html, это не так. Я использую Oracle, если это имеет значение.

Спасибо

Ответы [ 4 ]

11 голосов
/ 02 февраля 2011

Мне нравится использовать сравнение диапазонов, когда это возможно, поскольку оптимизатор может использовать его для сканирования индекса:

select inspections.name
  from inspections
 where inspections.date >= DATE '2010-06-01'
   and inspections.date < DATE '2010-07-01'
4 голосов
/ 02 февраля 2011

Я согласен с ответом Винсента, но для полноты вы можете упростить свой ответ до:

select inspections.name
from inspections
where
  to_char(inspections.insp_date, 'YYYYMM') = '201006';

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

create index x on inspections (to_char(insp_date, 'YYYYMM'));
3 голосов
/ 02 февраля 2011

Другой вариант будет

SELECT inspections.name
  FROM inspections
 WHERE TRUNC( inspections.insp_date, 'MM' ) = date '2010-06-01';

С точки зрения эффективности

  • Решение Винсента потенциально может использовать сканирование диапазона индекса INSP_DATE (при условии, что в таблице хранятся данные за многие месяцы, так что доступ к индексу будет наиболее эффективным планом).
  • Мой запрос может потенциально использовать основанный на функции индекс TRUNC (insp_date, 'MM'), снова предполагая, что таблица содержит данные за многие месяцы. Если количество строк в разные месяцы сильно отличается, оценки количества элементов оптимизатора могут быть немного более точными с этим индексом на основе функций, чем с прямым индексом INSP_DATE, но это вряд ли будет важным в запросе. это просто. Однако он может вступить в игру, если вы начнете вкладывать этот запрос в другое место. Однако, если вам необходимо индексировать INSP_DATE по другим причинам, поддержание двух разных индексов может оказаться трата времени и пространства.
  • Ваш начальный запрос и запрос Лева могут потенциально использовать составной индекс на основе функций (хотя вы захотите включить явный TO_NUMBER или сравнить со строками, а не числами, чтобы избежать неявных преобразований). Однако составной индекс, вероятно, будет наименее эффективным для поддержания (хотя мы говорим здесь об относительно небольших различиях) и представляется мне наименее чистым из альтернатив индекса.
3 голосов
/ 02 февраля 2011
select inspections.name
from inspections
where
  extract(year from inspections.insp_date) = 2010 and
  extract(month from inspections.insp_date) = 6;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...