如果created_at 字段已经被索引,我会简单地查找所有在X 和Y 之间具有created_at 值的行。这样就可以使用索引了。
例如,要在 2015 年的第 3 周获取具有 created_at 值的行,您可以运行:
select *
from questions
where created_at between '2015-01-11' and '2015-01-17'
这将允许使用索引。
如果您希望能够在 where 子句中指定一周,您可以使用 date_part 或 extract 函数在此表中添加一列存储年份和周#,然后对该列进行索引,以便查询可以利用它。
如果您不想添加列,当然可以在 where 子句中使用任一函数并查询表,但您将无法利用任何索引。
因为您提到不想在表中添加列,所以我建议添加基于函数的索引。
例如,如果您的 ddl 是:
create table questions
(
id int,
created_at timestamp,
title varchar(20)
);
insert into questions values
(1, '2014-12-31 09:43:42','"Add things"'),
(2, '2013-11-23 02:48:55','"How do I ruby?"'),
(3, '2015-01-15 15:11:19','"How do I python?"');
create or replace function to_week(ts timestamp)
returns text
as 'select concat(extract(year from ts),extract(week from ts))'
language sql
immutable
returns null on null input;
create index week_idx on questions (to_week(created_at));
你可以跑:
select q.*, to_week(created_at) as week
from questions q
where to_week(created_at) = '20153';
得到:
| ID | CREATED_AT | TITLE | WEEK |
|----|--------------------------------|--------------------|-------|
| 3 | January, 15 2015 15:11:19+0000 | "How do I python?" | 20153 |
(反映2015年第三周,即'20153')
小提琴: http://sqlfiddle.com/#!15/c77cd/3/0
你可以类似地运行:
select q.*,
concat(extract(year from created_at), extract(week from created_at)) as week
from questions q
where concat(extract(year from created_at), extract(week from created_at)) =
'20153';
小提琴: http://sqlfiddle.com/#!15/18c1e/3/0
但它不会利用基于函数的索引,因为没有。此外,它不会使用您在created_at 字段上可能拥有的任何索引,因为虽然该字段可能已被索引,但您实际上并没有在该字段上进行搜索。您正在搜索针对该字段应用的函数的结果。所以不能使用列本身的索引。
如果表很大,您将需要基于函数的索引或包含该周且本身已编入索引的列。