获取每周在SQL中创建的记录数

获取每周在SQL中创建的记录数,sql,ruby-on-rails,sqlite,postgresql,rails-activerecord,Sql,Ruby On Rails,Sqlite,Postgresql,Rails Activerecord,我有一张桌子,上面有问题。如何计算一周内提出的所有问题 更一般地说,如何在创建记录的一周内保存记录 Questions id created_at title ---------------------------------------------------- 1 2014-12-31 09:43:42 "Add things" 2 2013-11-23 02:98:55 "How do I ruby?" 3

我有一张桌子,上面有问题。如何计算一周内提出的所有问题

更一般地说,如何在创建记录的一周内保存记录

Questions
id     created_at            title            
----------------------------------------------------
1      2014-12-31 09:43:42   "Add things"
2      2013-11-23 02:98:55   "How do I ruby?"
3      2015-01-15 15:11:19   "How do I python?"
...
我使用的是SQLLite,但是PG答案也很好

或者,如果您使用Rails ActiveRecord获得了答案,这是惊人的,但不是必需的


我一直在尝试使用DATEPART(),但还没有找到任何成功的方法:

使用strfdate(%V)获取周数。 将其存储在DB中,并使用它来确定问题是在哪一周提出的

SQL也可以使用DATE_格式(datetime,“%u”)执行此操作

因此,请使用:

SELECT DATE_FORMAT(column,'%u') FROM Table

SQLite不像MS SQL Server那样具有本机日期时间类型,因此答案可能取决于存储日期的方式。并非所有的T-SQL都能在SQLite中工作

您可以将datetime存储为一个整数,该整数从1970年1月1日凌晨12:00开始计算秒数。一周有604800秒。所以你可以查询一个表达式,比如

rawdatetime / 604800 -- iff rawdatetime is integer

有关在SQLite中处理日期时间的更多信息,请参见此处:

如果在处创建的
字段已被索引,我只需查找所有在
处创建的
值在X和Y之间的行。这样就可以使用索引

例如,要获取在2015年第3周创建了值为
行,您可以运行:

select *
  from questions
 where created_at between '2015-01-11' and '2015-01-17'
这将允许使用索引

如果希望能够在where子句中指定一周,可以使用
date\u部分
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”

小提琴:

您可以类似地运行:

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';
小提琴:

但它不会利用基于函数的索引,因为没有。此外,它不会使用您在
created\u at
字段上可能有的任何索引,因为虽然该字段可能被索引,但您实际上没有在该字段上搜索。您正在搜索针对该字段应用的函数的结果。因此,无法使用列本身上的索引


如果表很大,您可能需要一个基于函数的索引,或者需要一个包含该周的列,该列本身已被索引。

在postgreSQL中,它很简单,如下所示:

SELECT id, created_at, title, date_trunc('week', created_at) created_week
  FROM Questions
SELECT id, created_at, title, date_trunc('week', created_at) created_week
     , COUNT(*) OVER ( PARTITION BY date_trunc('week', created_at) ) weekly_cnt
  FROM Questions
如果你想每周获得#个问题,只需执行以下操作:

SELECT date_trunc('week', created_at) created_week, COUNT(*) weekly_cnt
  FROM Questions
 GROUP BY date_trunc('week', created_at)
希望这有帮助。请注意,
date\u trunc()
将返回日期而不是数字(即,它不会返回一年中一周的序号)

更新:

此外,如果您想在一个查询中同时完成这两个任务,可以按如下方式执行:

SELECT id, created_at, title, date_trunc('week', created_at) created_week
  FROM Questions
SELECT id, created_at, title, date_trunc('week', created_at) created_week
     , COUNT(*) OVER ( PARTITION BY date_trunc('week', created_at) ) weekly_cnt
  FROM Questions

在上面的查询中,我使用了
COUNT(*)
作为窗口函数,并按创建问题的周进行分区。

这是可能的,但我不需要为此类查询创建任何中间表或额外列。请定义“周”。你是指ISO 8601定义(周一至周日)?你想把几周的时间和多年的时间混在一起吗?一年的第一周包含1月4日(ISO 8601)<代码>日期部分(),以及您的链接都是针对属于SQL Server的tSQL的。不适用于SQLite或Postgres。