我正在尝试编写一个SQL语句,它允许我检索9月份创建的所有订单而没有太多运气。
不工作:
select order_number, created_date
from orders
where created_date in to_date('2012-09', 'YYYY-MM');
工作但是太长了:
select order_number, created_date
from orders
where trunc(created_date) between to_date('2012-09-01', 'YYYY-MM-DD') and to_date('2012-09-30', 'YYYY-MM-DD');
答案 0 :(得分:5)
怎么样:
select order_number, created_date
from orders
where created_date >= to_date('2012-09-01', 'YYYY-MM-DD')
and created_date < to_date('2012-10-01', 'YYYY-MM-DD');
您应该尝试保持created_date
不变,以确保您可以很好地利用它上的索引。
答案 1 :(得分:4)
使用以下代码。
select order_number, created_date
from orders
where TO_CHAR(created_date, 'YYYY-MM') in '2012-09';
答案 2 :(得分:1)
我认为使用between
的版本会有更好的性能,但您可以尝试相反的方式:
WHERE TO_CHAR(created_date, 'YYYY-MM') = '2012-09';
另一种选择是EXTRACT:
WHERE
EXTRACT(year FROM created_date) = 2012
AND EXTRACT(month FROM created_date) = 9;
更新:
Function-Based Indexes可以用于 Oracle 8i 以提高此类查询的性能:
CREATE INDEX ORDS_CRTD_DT_YYYY_MM_IDX
ON orders (TO_CHAR(created_date, 'YYYY-MM'));
当然,你应该避免无缘无故地创建索引(它们会减慢写入操作),当你的问题有更简单的解决方案时 - 就像@Rob提供的那样 - 继续使用它。请记住,可以将TRUNC
,TO_CHAR
和EXTRACT
等功能与列配合使用,但仍然可以避免完全扫描。
答案 3 :(得分:0)
无需使用created_date
来重复between
列,即使查询继续使用该列上的索引(如果有的话),也可以使用trunc(to_date('2012-09','yyyy-mm'),'Month')
第一个日期,last_day(to_date('2012-09','yyyy-mm'))
表示该月的最后日期。
with orders(order_number, created_date) as
(
select 1, date'2012-08-31' from dual union all
select 2, date'2012-09-01' from dual union all
select 3, date'2012-09-02' from dual union all
select 4, date'2012-09-29' from dual union all
select 5, date'2012-09-30' from dual union all
select 6, date'2012-10-01' from dual
),
param(month) as
(
select to_date('2012-09','yyyy-mm') from dual
)
select order_number, created_date
from orders
cross join param
where created_date between trunc(month,'Month')
and last_day(month);
ORDER_NUMBER CREATED_DATE
------------ ------------
2 01.09.2012
3 02.09.2012
4 29.09.2012
5 30.09.2012